Beispiel #1
0
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}
Beispiel #2
0
	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
Beispiel #3
0
	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)
Beispiel #4
0
	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)
Beispiel #5
0
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}
Beispiel #6
0
	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
Beispiel #7
0
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}
Beispiel #8
0
	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}
Beispiel #9
0
	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()
Beispiel #10
0
	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
Beispiel #11
0
	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()
Beispiel #12
0
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,
	}