Example #1
0
 def __init__(self, db: InvokePSQL, ctx: Ctx,
              series_id: int,
              study_instance_id: int,
              encounter_repetitions: int,
              encounter_param_dict: Dict,
              tracer: TraceIt):
     self.db = db
     self.ctx = ctx
     self.ctx.series_id = series_id
     self.ctx.study_instance_id = study_instance_id
     self.method_last_call_audit = {}
     self.stats = SeriesStats(study_instance_id=self.ctx.study_instance_id, series_id=self.ctx.series_id)
     self.logger = RpgLogging(logger_name=ctx.logger_name)
     self.t = tracer
     self.encounter_repetitions = encounter_repetitions
     self.encounter_param_dict = encounter_param_dict
     self.party_name_param = None
     self.heroes = []
     self.hero_party_size_param = None
     self.opponent_party_size_param = None
     self.opponents = []
     self.series_stats = []
     self.encounter_stats = []
     self.character_stats = []
     self.assign_encounter_params()
     print(f"study_instance_id={study_instance_id} " 
           f"series_id={self.ctx.series_id} "
           f"encounter_repetitions={encounter_repetitions} "
           f"encounter_param_dict={encounter_param_dict} ")
     self.run_series()
Example #2
0
    def __init__(self, ctx, sides=20, debug_ind=False):
        """
        Randomization class

        :param sides: the number of sides this die will have (default: 20)
        :param debug_ind: log to class_eval array? (default: False)
        """
        self.sides = sides
        self.debug_ind = debug_ind
        self.details = []  # holds rollAmount objs
        self.method_last_call_audit = {}  # dict where method name key holds last crumb for that method
        self.logger = RpgLogging(logger_name=ctx.logger_name)
        self.ctx = ctx
Example #3
0
    def __init__(self, db, ctx: Ctx, tracer: TraceIt, app_username: str, study_name: str,
                 study_instance_id: int = None, repetitions: int = None):
        self.ctx = ctx
        self.method_last_call_audit = {}
        if self.ctx.app_username == "Unknown" or self.ctx.app_username == "Study_class_init":
            self.ctx.app_username = app_username

        self.logger = RpgLogging(logger_name=ctx.logger_name)
        self.t = tracer
        self.study_name = study_name
        self.repititions = repetitions
        if study_instance_id is None:
            # ----- TODO  ----------------
            # Get study information from db and create a new record in the study_instance table
            # Pass the context,
            self.study_instance_id = 1
            if self.ctx.study_instance_id == -1:
                self.log.debug("Updating Context for study instance id", self.ctx)
                self.ctx.study_instance_id = self.study_instance_id
        self.test_method_a(id=1)
        #

        self.log.debug("Leaving class init.", self.ctx)
Example #4
0
        out_str = '{'
        out_dict = self.__repr__()
        for key in out_dict.keys():
            out_str = f"{out_str}'{key}': {out_dict[key]}, "
        if out_str[-2:] == ", ":
            out_str = f'{out_str[:-2]}'
        out_str = f'{out_str}}}'
        return out_str


if __name__ == '__main__':
    db = InvokePSQL()
    logger_name = f'spell_main'
    ctx = Ctx(app_username='******', logger_name=logger_name)
    ctx.log_file_dir = os.path.expanduser('~/rpg/logs')
    logger = RpgLogging(logger_name=logger_name, level_threshold='debug')
    logger.setup_logging(log_dir=ctx.log_file_dir)
    try:
        a1 = Spell(db=db,
                   ctx=ctx,
                   name="Dragonborn Breath Weapon - Blue",
                   cast_at_level=None)
        print(a1)

    except Exception as error:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        print(f'Context Information:\n\t'
              f'App_username:      {ctx.app_username}\n\t'
              f'Full Name:         {ctx.fully_qualified}\n\t'
              f'Logger Name:       {ctx.logger_name}\n\t'
              f'Trace Id:          {ctx.trace_id}\n\t'
Example #5
0
    def test_method_b(self, id):
        self.log.debug("entering test method b", self.ctx)
        print(f"in test_method_b: {id}")
        self.test_method_c(id=3)

    @ctx_decorator()
    def test_method_c(self, id):
        self.log.debug("entering test method c", self.ctx)
        print(f"in test_method_c: {id}")


if __name__ == "__main__":
    study_id = random.randrange(0, 100000, 2)
    logger_name = f'study_main_{study_id}'
    ctx = Ctx(app_username='******', logger_name=logger_name)
    logger = RpgLogging(logger_name=logger_name, level_threshold='debug')
    logger.setup_logging()
    try:
        db = InvokePSQL()
        # series_dict = {
        #     "opponent_party_size": "4",
        #     "opponent_candidate": "Skeleton",
        #     "debug_ind": "1",
        #     "party_name": "AvgJoes_5"
        # }

        t = TraceIt("study")

        study = Study(db=db, ctx=ctx, app_username='******', study_name='Stats Compare', tracer=t)

    except Exception as error:
Example #6
0
class Die(object):
    @ctx_decorator
    def __init__(self, ctx, sides=20, debug_ind=False):
        """
        Randomization class

        :param sides: the number of sides this die will have (default: 20)
        :param debug_ind: log to class_eval array? (default: False)
        """
        self.sides = sides
        self.debug_ind = debug_ind
        self.details = []  # holds rollAmount objs
        self.method_last_call_audit = {}  # dict where method name key holds last crumb for that method
        self.logger = RpgLogging(logger_name=ctx.logger_name)
        self.ctx = ctx

    def add_method_last_call_audit(self, audit_obj):
        self.method_last_call_audit[audit_obj['methodName']] = audit_obj

    def get_method_last_call_audit(self, method_name='ALL'):
        if method_name == 'ALL':
            return_val = self.method_last_call_audit
        else:
            return_val = self.method_last_call_audit[method_name]
        return return_val

    def get_last_detail(self):
        """
        Return a list of the RollAmount dataclass instances
        """
        return self.details[-1]

    def get_details(self):
        """
        Return a list of the RollAmount dataclass instances
        """
        return self.details

    # _perform_roll should only be used by the other methods. The "_" at
    # the beginning of the name is a convention Python uses for
    # that sort of thing (more info: Python private method convention)
    # This simplifies the calls being done from the other methods

    @ctx_decorator
    def _perform_roll(self, rolls, dropvalue=False,
                      dropfrom="Low", halved=False):
        """
        Handles the calculations for the class.

        :param rolls:     How many rolls to do
        :param dropvalue: Drop a value? (default: False)
        :param dropfrom:  If Dropping, from which end? (default: "Low")
        :param halved:    Cut sum in half? (default: False)

        """
        t_roll_details = RollAmount(die_used=self.sides)
        t_roll_details.die_rolls = rolls
        # print(f'adding roll id: {t_roll_details.roll_id} to {ctx.crumbs[-1]}')
        self.ctx.add_roll_id(t_roll_details.roll_id)
        if dropvalue:
            t_roll_details.adjustment_values["dropvalue"] = dropvalue
            t_roll_details.adjustment_values["dropfrom"] = dropfrom
        if halved:
            t_roll_details.adjustment_values["halved"] = halved

        tmp_hold = []  # list to hold all rolled values
        tot = 0       # variable to hold the total sum value

        for x in range(0, rolls):  # place the roll results in the tmpHold list
            raw_roll = random.randint(1, self.sides)
            tmp_hold.append(raw_roll)
            t_roll_details.base_roll.append(raw_roll)

        # If dropping from either side, sort the array accordingly
        if dropvalue:
            if dropfrom == "High":
                tmp_hold.sort(reverse=True)
            else:
                tmp_hold.sort()

            del tmp_hold[0]  # then remove the first value

        for y in tmp_hold:  # compute the sum of all values left
            tot = tot + y

        if halved:  # halve value rounding down (floor)
            tot = tot // 2

        t_roll_details.die_total_used = tot

        self.details.append(t_roll_details)

        self.logger.info(msg='roll_audit', json_dict=t_roll_details.__dict__, ctx=self.ctx)

        return tot

    @ctx_decorator
    def roll(self, rolls=1, droplowest=False):
        """
        Perform a number of standard rolls and return the sum

        :param rolls: How many times to roll the die (Default: 1)
        :param droplowest: Drop the lowest value? (Default: False)

        """
        if droplowest:
            result = self._perform_roll(rolls=rolls, dropvalue=True, dropfrom="Low")
        else:
            result = self._perform_roll(rolls=rolls, dropvalue=False)

        return result

    @ctx_decorator
    def roll_with_advantage(self):
        """
        Perform a single roll with advantage

        """
        return self._perform_roll(rolls=2, dropvalue=True, dropfrom="Low")

    @ctx_decorator
    def roll_with_disadvantage(self):
        """
        Perform a single roll with disadvantage

        """
        return self._perform_roll(rolls=2, dropvalue=True, dropfrom="High")

    @ctx_decorator
    def roll_with_resistance(self, rolls):
        """
        Perform rolls and return half the total sum

        """
        return self._perform_roll(rolls=rolls, dropvalue=False, halved=True)

    @ctx_decorator
    def get_sum(self, startingval, multiplier):
        return startingval + self.roll(rolls=multiplier)
Example #7
0
class Series(object):
    @ctx_decorator
    def __init__(self, db: InvokePSQL, ctx: Ctx,
                 series_id: int,
                 study_instance_id: int,
                 encounter_repetitions: int,
                 encounter_param_dict: Dict,
                 tracer: TraceIt):
        self.db = db
        self.ctx = ctx
        self.ctx.series_id = series_id
        self.ctx.study_instance_id = study_instance_id
        self.method_last_call_audit = {}
        self.stats = SeriesStats(study_instance_id=self.ctx.study_instance_id, series_id=self.ctx.series_id)
        self.logger = RpgLogging(logger_name=ctx.logger_name)
        self.t = tracer
        self.encounter_repetitions = encounter_repetitions
        self.encounter_param_dict = encounter_param_dict
        self.party_name_param = None
        self.heroes = []
        self.hero_party_size_param = None
        self.opponent_party_size_param = None
        self.opponents = []
        self.series_stats = []
        self.encounter_stats = []
        self.character_stats = []
        self.assign_encounter_params()
        print(f"study_instance_id={study_instance_id} " 
              f"series_id={self.ctx.series_id} "
              f"encounter_repetitions={encounter_repetitions} "
              f"encounter_param_dict={encounter_param_dict} ")
        self.run_series()

    def add_method_last_call_audit(self, audit_obj):
        self.method_last_call_audit[audit_obj['methodName']] = audit_obj

    def get_method_last_call_audit(self, method_name='ALL'):
        if method_name == 'ALL':
            return_val = self.method_last_call_audit
        else:
            return_val = self.method_last_call_audit[method_name]
        return return_val

    @ctx_decorator
    def assign_encounter_params(self):
        if 'party_name' in self.encounter_param_dict.keys():
            self.party_name_param = self.encounter_param_dict['party_name']
        if 'hero_party_size' in self.encounter_param_dict.keys():
            self.hero_party_size_param = self.encounter_param_dict['hero_party_size']
        if 'opponent_party_size' in self.encounter_param_dict.keys():
            self.opponent_party_size_param = self.encounter_param_dict['opponent_party_size']
        if 'opponent_candidate' in self.encounter_param_dict.keys():
            self.opponent_candidate_param = self.encounter_param_dict['opponent_candidate']

    @ctx_decorator
    def get_named_party(self):
        p = []
        sql = f"select count(name) from dnd_5e.party where name = '{self.party_name_param}'"
        res = self.db.query(sql)
        hero_party_size = int(res[0][0])
        if hero_party_size == 0:
            raise Exception(f'Party {self.party_name_param} could not be found.')
        full_party = Party(db=self.db, ctx=self.ctx, name=self.party_name_param)
        for tmp_char in full_party.get_party():
            p.append(tmp_char)
        return p

    @ctx_decorator
    def get_foes(self):
        f = []

        for opponent_counter in range(int(self.opponent_party_size_param)):
            if self.opponent_candidate_param:
                show_counter = opponent_counter + 1
                t_name = f"{self.opponent_candidate_param}({show_counter})"
            else:
                t_name = None
            f.append(Foe(db=self.db, ctx=self.ctx,
                         foe_candidate=self.opponent_candidate_param,
                         foe_name=t_name))
        return f

    @ctx_decorator
    def run_series(self):
        for series_counter in range(self.encounter_repetitions):
            display_repetition = series_counter + 1
            print(f"Encounter Repetition: {display_repetition}")
            heroes = self.get_named_party()
            opponents = self.get_foes()
            for Hero in heroes:
                print(f"  {Hero.get_name()}")
            print(f"Against:")
            for Opponent in opponents:
                print(f"  {Opponent.get_name()}")
            e = Encounter(ctx=self.ctx,
                          heroes=heroes,
                          opponents=opponents,
                          tracer=self.t.tracer,
                          encounter_id=series_counter)
            self.encounter_stats.append(e.get_encounter_stats())
            print(f"The winning party was: {e.winning_list_name} in {self.ctx.round} rounds.")
            print(f"The surviving {e.winning_list_name} members:")
            for i in range(len(e.winning_list)):
                if e.winning_list[i].alive:
                    print(f'{e.winning_list[i].get_name()}')
            # print(f"Character damage info:")
            print("------------------ Character Stats --------------------")
            for Hero in heroes:
                # t_char_stats = CharacterStats(study_instance_id=self.study_instance_id,
                #                               series_id=self.series_id,
                #                               encounter_id=series_counter,
                #                               character_id=Hero.character_id,
                #                               character_name=Hero.get_name(),
                #                               character_class=Hero.get_class(),
                #                               character_race=Hero.get_race(),
                #                               character_level=Hero.level,
                #                               attack_rolls= Hero.attack_rolls,
                #                               attack_attempts=Hero.attack_roll_count,
                #                               attack_successes=Hero.attack_success_count,
                #                               attack_nat20_count=Hero.attack_roll_nat20_count,
                #                               attack_nat1_count=Hero.attack_roll_nat1_count,
                #                               damage_dealt_dict=Hero.get_damage_dealt(),
                #                               damage_taken_dict=Hero.get_damage_taken())

                # t_encounter_stats.heroes.append(t_char_stats)
                # t_dict = Hero.get_damage_dealt()
                # print(f"  {Hero.get_name()} attacks: {Hero.attack_success_count}/{Hero.attack_roll_count}"
                #       f" nat20s:{Hero.attack_roll_nat20_count} nat1s: {Hero.attack_roll_nat1_count}")
                # print(Hero.attack_rolls)
                # print(f"  {Hero.get_name()} damage dealt ({t_dict['Total']}): {Hero.get_damage_dealt()}")
                # t_dict = Hero.get_damage_taken()
                # print(f"  {Hero.get_name()} damage taken ({t_dict['Total']}): {Hero.get_damage_taken()}")
                print(fix_dict_for_json(Hero.stats.__dict__))
            for Opponent in opponents:
                # t_char_stats = CharacterStats(study_instance_id=self.study_instance_id,
                #                               series_id=self.series_id,
                #                               encounter_id=series_counter,
                #                               character_id=-1,
                #                               character_name=Opponent.get_name(),
                #                               character_class='Foe',
                #                               character_race=Opponent.get_race(),
                #                               character_level=Opponent.level,
                #                               attack_rolls=Opponent.attack_rolls,
                #                               attack_attempts=Opponent.attack_roll_count,
                #                               attack_successes=Opponent.attack_success_count,
                #                               attack_nat20_count=Opponent.attack_roll_nat20_count,
                #                               attack_nat1_count=Opponent.attack_roll_nat1_count,
                #                               damage_dealt_dict=Opponent.get_damage_dealt(),
                #                               damage_taken_dict=Opponent.get_damage_taken()
                #                               )
                # t_encounter_stats.opponents.append(t_char_stats)
                # t_dict = Opponent.get_damage_dealt()
                # print(f"  {Opponent.get_name()} attacks: {Opponent.attack_success_count}/{Opponent.attack_roll_count}"
                #       f" nat20s: {Opponent.attack_roll_nat20_count} nat1s: {Opponent.attack_roll_nat1_count}")
                # print(Opponent.attack_rolls)
                # print(f"  {Opponent.get_name()} damage dealt ({t_dict['Total']}): {Opponent.get_damage_dealt()}")
                # t_dict = Opponent.get_damage_taken()
                # print(f"  {Opponent.get_name()} damage taken ({t_dict['Total']}): {Opponent.get_damage_taken()}")
                print(fix_dict_for_json(Opponent.stats.__dict__))
            # print(e.get_characters_stats())
            # self.stats.update_totals()
            self.logger.info(ctx=self.ctx, msg='character_stats',
                              json_dict=fix_dict_for_json(e.get_characters_stats()))
            print("------------------ Encounter Stats --------------------")
            print(fix_dict_for_json(e.stats.__dict__))

        print("------------------ Series Stats --------------------")
        print(fix_dict_for_json(self.stats.__dict__))
        self.logger.info(ctx=self.ctx, msg='series_stats', json_dict=fix_dict_for_json(self.stats.get_dict()))