def joinable (request): rules_ids_sq = DBSession.query(models.GameRules.id).order_by(models.GameRules.ctime.desc()) joined_games_sq = DBSession.query(models.SessionCharacter.game_session_id).filter_by(user_id = request.user.id).subquery() rules_sessions = (DBSession.query(models.GameRules.id, models.GameRules.title, models.GameRules.max_players, func.count(models.GameSession.id).label('sessions_num')) .join(models.GameSession, models.GameSession.rules_id == models.GameRules.id) .filter(models.GameRules.id.in_(rules_ids_sq)) .filter(models.GameRules.max_players > models.GameSession.players_joined) .filter(models.GameSession.status != constants.GameSessionStatuses.CLOSED) .filter(~models.GameSession.id.in_(joined_games_sq)) .group_by(models.GameRules.id, models.GameRules.title, models.GameRules.max_players) ) pages_total = math.ceil(rules_sessions.count() / float(forms.PageForm.LIMIT)) if not pages_total: return {'rules_sessions': {}} form = forms.PageForm(request.GET, pages_total = pages_total) if not form.validate(): return HTTPFound(location = request.route_url('games.joinable')) offset = (form.page.data - 1) * form.LIMIT rules_sessions = rules_sessions.offset(offset).limit(form.LIMIT) return {'rules_sessions': rules_sessions}
def get_skill_by_title (self, skill_title): # TODO: avoid usage of this func by denormalization? skill = DBSession.query(Skill.id).filter_by(title = skill_title).first() if not skill: # TODO raise return skill
def validate_skill (self, skill): if not skill.formula: return self.dynamic_keywords = [skill.title,] variable_names = self.get_formula_variable_names(skill.formula) parent_skills = DBSession.query(models.Skill).filter( models.Skill.rules_id == self.rules_id, models.Skill.title.in_(variable_names) ) for parent_skill in parent_skills: self.validate_skill(parent_skill)
def get_child_query_by_priority (self, child_name): CHILD_NAME_TO_MODEL_MAPPER = { 'skills_categories': SkillCategory, 'skills': Skill, 'perks': Perk, 'items': Item, 'item_groups': ItemGroup, 'races': Race, 'character_class': CharacterClass, 'dices': Dice, } _model = CHILD_NAME_TO_MODEL_MAPPER[child_name] # partition_by = rules_id ? return DBSession.query(_model, func.row_number().over(order_by = _model.priority).label('_priority')).filter_by(rules_id = self.id)
def joined (request): # TODO: Pagination session_ids_sq = DBSession.query(models.SessionCharacter.game_session_id).filter_by(user_id = request.user.id).subquery() sessions = models.GameSession.query.filter( models.GameSession.id.in_(session_ids_sq), models.GameSession.status != constants.GameSessionStatuses.CLOSED, ) characters = models.SessionCharacter.query.filter_by(user_id = request.user.id) session_roles = {} for character in characters: session_roles[character.game_session_id] = character.user_role return {'sessions': sessions, 'session_roles': session_roles}
def get_skills (self): skills_dict = {} # Base for skill_id in self.skills.keys(): base_value = self.skills[skill_id] skill_id = int(skill_id) skills_dict[skill_id] = { 'base_value': base_value, 'effective_value': self.get_skill_effective_value(skill_id), } # Add the character's race if self.race_id: race = Race.query.get(self.race_id) for skill_id, skill_val in race.skills.viewitems(): skill_id = int(skill_id) skills_dict.setdefault(skill_id, {'effective_value': 0, 'base_value': 0}) skills_dict[skill_id]['effective_value'] += skill_val # Add the character's class if self.class_id: char_class = CharacterClass.query.get(self.class_id) if char_class.skills: for skill_id, skill_val in char_class.skills.viewitems(): skill_id = int(skill_id) skills_dict.setdefault(skill_id, {'effective_value': 0, 'base_value': 0}) skills_dict[skill_id]['effective_value'] += skill_val # Worn items worn_session_items_query = self.items_query.filter(SessionItem.attrs['is_equippable'].cast(Boolean) == True).options(joinedload('item')) for session_item in worn_session_items_query: item_group_id_sq = DBSession.query(Item.group_id).filter_by(id = session_item.item_id).subquery() item_group = ItemGroup.query.filter_by(id = item_group_id_sq, is_equippable = True).first() if not item_group: continue item = session_item.item for skill_id, skill_val in item.skills.viewitems(): skill_id = int(skill_id) skills_dict.setdefault(skill_id, {'effective_value': 0, 'base_value': 0}) skills_dict[skill_id]['effective_value'] += skill_val # TODO: Used items return skills_dict
def joinable_rules (request): # TODO: Pagination joined_games_sq = DBSession.query(models.SessionCharacter.game_session_id).filter_by(user_id = request.user.id).subquery() sessions = (models.GameSession.query .join(models.GameRules, models.GameSession.rules_id == models.GameRules.id) .filter( models.GameRules.id == request.matchdict['rules_id'], models.GameSession.players_joined < models.GameRules.max_players, models.GameSession.status != constants.GameSessionStatuses.CLOSED, ~models.GameSession.id.in_(joined_games_sq), ) ) return {'sessions': sessions}
def handle (self): character_id = State.clients_sockets[self.websocket] game_session_id = self.game_session_id.data character = models.SessionCharacter.query.filter_by(id = character_id, game_session_id = game_session_id).first() if not character or character.user_role != "player": return error_response('Forbidden') new_skills_dict = {skill['id']: skill['value'] for skill in self.skills.data} skills = DBSession.query(models.Skill.id, models.Skill.category_id, models.Skill.formula).filter(models.Skill.id.in_(character.skills.keys())).all() skills_categories_mapper = {skill.id: skill.category_id for skill in skills} skills_with_formulas = {skill.id: True for skill in skills if skill.formula} char_skills = copy.copy(character.skills) char_skill_points = copy.copy(character.skill_points) for skill_id, val_to_add in new_skills_dict.viewitems(): if val_to_add <= 0: continue # TODO: error? if skill_id in skills_with_formulas: continue skill_id = int(skill_id) category_id = skills_categories_mapper[skill_id] cat_points = char_skill_points[str(category_id)] if cat_points < val_to_add: continue # TODO: error? char_skills[str(skill_id)] += val_to_add char_skill_points[str(category_id)] -= val_to_add character.skills = char_skills character.skill_points = char_skill_points character.add() DBSession.commit() character.add() skills = character.get_skills() data = {'character_id': character_id, 'skills': skills, 'skill_points': character.skill_points} self.group_call_client_action("AfterCharacterChangeSkills", data, include_sender = True) return {'success': True, 'skills': skills}
def get_role_for_session (self, game_session_id): return DBSession.query(SessionCharacter.user_role).filter(SessionCharacter.user_id == self.id, SessionCharacter.game_session_id == game_session_id).scalar()
def get_next_rules_child_priority (self, rules_id, child_class): priority = DBSession.query(child_class.priority + 1).filter(child_class.rules_id == rules_id).order_by('-priority').limit(1).scalar() or 0 return priority
def owned_rules_child (self, child_id, child_class): rules_subquery = DBSession.query(GameRules.id).filter_by(creator_id = self.id).subquery() return child_class.query.filter(child_class.rules_id.in_(rules_subquery), child_class.id == child_id).first()
def play (request): form_data = h.update_request_params(request.matchdict) form = forms.Play(form_data) if not form.validate(): return HTTPUnprocessableEntity() game_session_id = form.game_session_id.data game_session = models.GameSession.query.filter_by(id = game_session_id, status = constants.GameSessionStatuses.AVAILABLE).first() if not game_session: return HTTPFound(location = request.route_url('games.list')) user_role = request.user.get_role_for_session(game_session_id) if user_role is None: return HTTPFound(location = request.route_url('games.join', game_session_id = game_session_id)) rules_id_sq = DBSession.query(models.GameSession.rules_id).filter_by(id = game_session_id).subquery() rules = models.GameRules.query.filter_by(id = rules_id_sq).first() if not rules: return HTTPUnprocessableEntity() master = models.SessionCharacter.query.filter_by(game_session_id = game_session_id, user_role = "master").first() character = models.SessionCharacter.query.filter_by(game_session_id = game_session_id, user_id = request.user.id).first() players = [] the_player = None the_player_id = -1 character_token = None if not character: user_role = "spectator" elif master.id == character.id: user_role = "master" character_token = master.token else: the_player = character the_player_id = character.id players.append(character) user_role = "player" character_token = character.token other_players = models.SessionCharacter.query.filter(models.SessionCharacter.game_session_id == game_session_id, models.SessionCharacter.user_role == "player", models.SessionCharacter.user_id != request.user.id).order_by('id').all() players += other_players players_dicts = [] for player in players: with_items = the_player is not None and player.id == the_player.id players_dicts.append(player.as_dict(with_items = with_items)) cols_for_char_tbl = _get_cols_for_characters_table(rules) item_groups = [] for item_group_query_tpl in rules.get_child_query_by_priority('item_groups').filter_by(is_disabled = False): item_groups.append({ 'id': item_group_query_tpl.ItemGroup.id, 'title': item_group_query_tpl.ItemGroup.title, }) skills_categories = [cat.as_dict() for cat in models.SkillCategory.query.filter_by(rules_id = rules.id, is_disabled = False)] items = [x.as_dict() for x in rules.items_query.filter_by(is_disabled = False)] skills = {} for skill in rules.skills_query.filter_by(is_disabled = False): skills.setdefault(skill.id, {}) skills[skill.id].update(skill.as_dict()) skills[skill.id].setdefault('related_skills', []) if skill.formula.strip() and master.id != character.id: node = ast.parse(skill.formula, mode = 'eval') # TODO: exceptions? visitor = formula.VariablesCollectionVisitor({}) visitor.visit(node) related_skills = rules.skills_query.filter(models.Skill.title.in_(visitor.VARIABLE_NAMES)) for related_skill in related_skills: skills.setdefault(related_skill.id, {}) skills[related_skill.id].setdefault('related_skills', []) skills[related_skill.id]['related_skills'].append(skill.id) token_tools = [] defaults = constants.PlayfieldObject.get_defaults(request.static_url('boardless:static/')) for obj_type in constants.PlayfieldObject.GENERAL_OBJECTS_ORDER: token_tools.append({ 'type': obj_type, 'title': defaults[obj_type]['title'], 'img_url': defaults[obj_type]['img_url'], }) return { 'colors': COLORS, 'game_session_id': game_session_id, 'the_player_id': the_player_id, 'character_token': character_token, 'master': master, 'players': players_dicts, 'cols_for_char_tbl': cols_for_char_tbl, 'skills': skills, 'item_groups': item_groups, 'rules': rules, 'user_role': user_role, 'skills_categories': skills_categories, 'token_tools': token_tools, 'items': items, 'dices': {d.id: d.as_dict(static_path = request.static_url('boardless:static/')) for d in rules.dices}, 'constants': constants, }