<commit_before># -*- coding: utf-8 -*-
"""
Copyright (c) Microsoft Open Technologies (Shanghai) Co. Ltd.  All rights reserved.
 
The MIT License (MIT)
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""

import sys
from werkzeug.exceptions import Forbidden

sys.path.append("..")

from flask import g
from sqlalchemy import and_

from hackathon import Component, RequiredFeature
from hackathon.database import Team, UserTeamRel, User, Hackathon, TeamScore, TeamShow, Award, TeamAward
from hackathon.hackathon_response import not_found, bad_request, precondition_failed, ok, forbidden
from hackathon.constants import TeamMemberStatus, Team_Show_Type

__all__ = ["TeamManager"]


class TeamManager(Component):
    """Component to manage hackathon teams"""
    user_manager = RequiredFeature("user_manager")
    admin_manager = RequiredFeature("admin_manager")
    register_manager = RequiredFeature("register_manager")
    hackathon_template_manager = RequiredFeature("hackathon_template_manager")

    def get_team_by_id(self, team_id):
        team = self.__get_team_by_id(team_id)

        # check whether it's anonymous user or not
        user = None
        if self.user_manager.validate_login():
            user = g.user

        if team:
            return self.__team_detail(team, user)
        else:
            return not_found()

    def get_team_by_name(self, hackathon_id, team_name):
        """ get user's team basic information stored on table 'team' based on team name

        :type hackathon_id: int
        :param hackathon_id: id of hackathon related to the team

        :type team_name: str | unicode
        :param team_name: name of the team

        :rtype: dict
        :return: team's information as a dict if team is found otherwise not_found()
        """
        team = self.__get_team_by_name(hackathon_id, team_name)

        # check whether it's anonymous user or not
        user = None
        if self.user_manager.validate_login():
            user = g.user

        if team:
            return self.__team_detail(team, user)
        else:
            return not_found("no such team")

    def get_team_members(self, team_id):
        """Get team member list of specific team

        :rtype: dict
        :return: team's information and team's members list if team is found otherwise not_found()
        """
        rels = self.db.find_all_objects_by(UserTeamRel, team_id=team_id)

        def sub(t):
            m = t.dic()
            m["user"] = self.user_manager.user_display_info(t.user)
            return m

        return map(lambda t: sub(t), rels)

    def get_hackathon_team_list(self, hackathon_id, name=None, number=None):
        """Get the team list of selected hackathon

        :type hackathon_id: int
        :param hackathon_id: hackathon id

        :type name: str|unicode
        :param name: name of team. optional

        :type number: int
        :param number: querying condition, return number of teams

        :rtype: list
        :return: a list of team filter by name and number on selected hackathon
        """
        hackathon_team_list = self.db.find_all_objects_by(Team, hackathon_id=hackathon_id)
        if name is not None:
            hackathon_team_list = filter(lambda t: name in t.name, hackathon_team_list)
        if number is not None:
            hackathon_team_list = hackathon_team_list[0:number]

        # check whether it's anonymous user or not
        user = None
        if self.user_manager.validate_login():
            user = g.user

        hackathon_team_list = map(lambda x: self.__team_detail(x, user), hackathon_team_list)
        return hackathon_team_list

    def create_default_team(self, hackathon, user):
        """Create a default new team for user after registration.

        Use user name as team name by default. Append user id in case user name is duplicate
        """
        user_team_rel = self.__get_valid_team_by_user(user.id, hackathon.id)
        if user_team_rel:
            self.log.debug("fail to create team since user is already in some team.")
            return precondition_failed("you must leave the current team first")

        team_name = self.__generate_team_name(hackathon, user)
        team = Team(name=team_name,
                    leader_id=user.id,
                    logo=user.avatar_url,
                    hackathon_id=hackathon.id)
        self.db.add_object(team)

        user_team_rel = UserTeamRel(join_time=self.util.get_now(),
                                    status=TeamMemberStatus.Approved,
                                    hackathon_id=hackathon.id,
                                    user_id=user.id,
                                    team_id=team.id)
        self.db.add_object(user_team_rel)

        return team.dic()

    def update_team(self, kwargs):
        """Update existing team information

        :type kwargs: dict
        :param kwargs: a dict to store update information for team

        :rtype: dict
        :return: updated team information in a dict
        """
        team = self.__get_team_by_id(kwargs["id"])
        if not team:
            return not_found("team not exists")

        # avoid duplicate team with same names
        if "name" in kwargs and kwargs["name"] != team.name:
            if self.__get_team_by_name(g.hackathon.id, kwargs["name"]):
                return precondition_failed("team with the same name exists already")

        self.__validate_team_permission(g.hackathon.id, team, g.user)
        self.db.update_object(team,
                              name=kwargs.get("name", team.name),
                              description=kwargs.get("description", team.description),
                              logo=kwargs.get("logo", team.logo),
                              update_time=self.util.get_now())
        return self.__team_detail(team)

    def dismiss_team(self, operator, team_id):
        """Dismiss a team by team leader or hackathon admin

        :rtype: bool
        :return: if dismiss success, return ok. if not ,return bad request.
        """
        team = self.__get_team_by_id(team_id)
        if not team:
            return ok()

        hackathon = team.hackathon
        self.__validate_team_permission(hackathon.id, team, operator)

        members = self.db.find_all_objects_by(UserTeamRel, team_id=team.id, status=TeamMemberStatus.Approved)
        member_users = [m.user for m in members]

        # delete all team members first
        self.db.delete_all_objects_by(UserTeamRel, team_id=team.id)
        self.db.delete_object(team)

        for u in member_users:
            self.create_default_team(hackathon, u)

        return ok()

    def quit_team_forcedly(self, team_id, user):
        """
        The operator(admin or superadmin) forces a user(team leader or other members) to quit a team.
        If the user is the only member of the team, the team will be deleted.
        Else if the user is the leader of a team with several members, the team will be decomposed into several
        new teams.
        Else if the user is not the leader of a team with several members, just the user quits the team.

        :rtype: bool
        :return: if dismiss success, return ok. if not ,return bad request.
        """
        team = self.__get_team_by_id(team_id)
        if not team:
            return not_found("team not exists")

        # here we don't check whether the operator has the permission,

        members = self.db.find_all_objects_by(UserTeamRel, team_id=team.id, status=TeamMemberStatus.Approved)
        if not members or len(members) == 0:
            return not_found("this team doesn't have any members")
        member_users = [m.user for m in members]

        num_team_members = len(member_users)
        hackathon = team.hackathon
        if num_team_members > 1:
            if team.leader_id == user.id:
                self.db.delete_all_objects_by(UserTeamRel, team_id=team.id)
                self.db.delete_object(team)
                for u in member_users:
                    if u.id != user.id:
                        self.create_default_team(hackathon, u)
            else:
                self.db.delete_all_objects_by(UserTeamRel, user_id=user.id, team_id=team_id)
        elif num_team_members == 1:
            self.db.delete_all_objects_by(UserTeamRel, team_id=team.id)
            self.db.delete_object(team)
        else:
            return not_found("this team doesn't have any members")

        return ok()

    def join_team(self, user, team_id):
        """Join a team will create a record on user_team_rel table which status will be 0.

        :type user: User
        :param user: the user to join a team

        :rtype: dict
        :return: if user already joined team or team not exist, return bad request. Else, return a dict of joined
            details.
        """
        if self.db.find_first_object_by(UserTeamRel, user_id=user.id, team_id=team_id):
            return ok("You already joined this team.")

        team = self.__get_team_by_id(team_id)
        if not team:
            return not_found()

        cur_team = self.__get_valid_team_by_user(user.id, team.hackathon_id)
        if cur_team and cur_team.team.user_team_rels.count() > 1:
            return precondition_failed("Team leader cannot join another team for team member count greater than 1")

        if not self.register_manager.is_user_registered(user.id, team.hackathon):
            return precondition_failed("user not registerd")

        candidate = UserTeamRel(join_time=self.util.get_now(),
                                update_time=self.util.get_now(),
                                status=TeamMemberStatus.Init,
                                hackathon_id=team.hackathon.id,
                                user_id=user.id,
                                team_id=team.id)
        self.db.add_object(candidate)
        return candidate.dic()

    def update_team_member_status(self, operator, user_team_rel_id, status):
        """ update user's status on selected team. if current user doesn't have permission, return bad request.
        Else, update user's status

        :type status: int
        :param status: the status of the team member, see TeamMemberStatus in constants.py

        :rtype: bool
        :return: if update success, return ok. if not , return bad request.
        """
        rel = self.db.find_first_object_by(UserTeamRel, id=user_team_rel_id)
        if not rel:
            return not_found()

        team = rel.team
        self.__validate_team_permission(rel.hackathon_id, team, operator)

        if rel.user_id == team.leader_id:
            return precondition_failed("cannot update status of team leader")

        if status == TeamMemberStatus.Approved:
            # disable previous team first
            self.db.delete_all_objects_by(UserTeamRel,
                                          hackathon_id=rel.hackathon_id,
                                          user_id=rel.user_id,
                                          status=TeamMemberStatus.Approved)
            self.db.delete_all_objects_by(Team, hackathon_id=rel.hackathon_id, leader_id=rel.user_id)

            rel.status = TeamMemberStatus.Approved
            rel.update_time = self.util.get_now()
            self.db.commit()
            return ok("approved")<commit_msg>fix problem of 2 click approval will not approve the user to join the team<commit_after># -*- coding: utf-8 -*-
"""
Copyright (c) Microsoft Open Technologies (Shanghai) Co. Ltd.  All rights reserved.
 
The MIT License (MIT)
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""

import sys
from werkzeug.exceptions import Forbidden

sys.path.append("..")

from flask import g
from sqlalchemy import and_

from hackathon import Component, RequiredFeature
from hackathon.database import Team, UserTeamRel, User, Hackathon, TeamScore, TeamShow, Award, TeamAward
from hackathon.hackathon_response import not_found, bad_request, precondition_failed, ok, forbidden
from hackathon.constants import TeamMemberStatus, Team_Show_Type

__all__ = ["TeamManager"]


class TeamManager(Component):
    """Component to manage hackathon teams"""
    user_manager = RequiredFeature("user_manager")
    admin_manager = RequiredFeature("admin_manager")
    register_manager = RequiredFeature("register_manager")
    hackathon_template_manager = RequiredFeature("hackathon_template_manager")

    def get_team_by_id(self, team_id):
        team = self.__get_team_by_id(team_id)

        # check whether it's anonymous user or not
        user = None
        if self.user_manager.validate_login():
            user = g.user

        if team:
            return self.__team_detail(team, user)
        else:
            return not_found()

    def get_team_by_name(self, hackathon_id, team_name):
        """ get user's team basic information stored on table 'team' based on team name

        :type hackathon_id: int
        :param hackathon_id: id of hackathon related to the team

        :type team_name: str | unicode
        :param team_name: name of the team

        :rtype: dict
        :return: team's information as a dict if team is found otherwise not_found()
        """
        team = self.__get_team_by_name(hackathon_id, team_name)

        # check whether it's anonymous user or not
        user = None
        if self.user_manager.validate_login():
            user = g.user

        if team:
            return self.__team_detail(team, user)
        else:
            return not_found("no such team")

    def get_team_members(self, team_id):
        """Get team member list of specific team

        :rtype: dict
        :return: team's information and team's members list if team is found otherwise not_found()
        """
        rels = self.db.find_all_objects_by(UserTeamRel, team_id=team_id)

        def sub(t):
            m = t.dic()
            m["user"] = self.user_manager.user_display_info(t.user)
            return m

        return map(lambda t: sub(t), rels)

    def get_hackathon_team_list(self, hackathon_id, name=None, number=None):
        """Get the team list of selected hackathon

        :type hackathon_id: int
        :param hackathon_id: hackathon id

        :type name: str|unicode
        :param name: name of team. optional

        :type number: int
        :param number: querying condition, return number of teams

        :rtype: list
        :return: a list of team filter by name and number on selected hackathon
        """
        hackathon_team_list = self.db.find_all_objects_by(Team, hackathon_id=hackathon_id)
        if name is not None:
            hackathon_team_list = filter(lambda t: name in t.name, hackathon_team_list)
        if number is not None:
            hackathon_team_list = hackathon_team_list[0:number]

        # check whether it's anonymous user or not
        user = None
        if self.user_manager.validate_login():
            user = g.user

        hackathon_team_list = map(lambda x: self.__team_detail(x, user), hackathon_team_list)
        return hackathon_team_list

    def create_default_team(self, hackathon, user):
        """Create a default new team for user after registration.

        Use user name as team name by default. Append user id in case user name is duplicate
        """
        user_team_rel = self.__get_valid_team_by_user(user.id, hackathon.id)
        if user_team_rel:
            self.log.debug("fail to create team since user is already in some team.")
            return precondition_failed("you must leave the current team first")

        team_name = self.__generate_team_name(hackathon, user)
        team = Team(name=team_name,
                    leader_id=user.id,
                    logo=user.avatar_url,
                    hackathon_id=hackathon.id)
        self.db.add_object(team)

        user_team_rel = UserTeamRel(join_time=self.util.get_now(),
                                    status=TeamMemberStatus.Approved,
                                    hackathon_id=hackathon.id,
                                    user_id=user.id,
                                    team_id=team.id)
        self.db.add_object(user_team_rel)

        return team.dic()

    def update_team(self, kwargs):
        """Update existing team information

        :type kwargs: dict
        :param kwargs: a dict to store update information for team

        :rtype: dict
        :return: updated team information in a dict
        """
        team = self.__get_team_by_id(kwargs["id"])
        if not team:
            return not_found("team not exists")

        # avoid duplicate team with same names
        if "name" in kwargs and kwargs["name"] != team.name:
            if self.__get_team_by_name(g.hackathon.id, kwargs["name"]):
                return precondition_failed("team with the same name exists already")

        self.__validate_team_permission(g.hackathon.id, team, g.user)
        self.db.update_object(team,
                              name=kwargs.get("name", team.name),
                              description=kwargs.get("description", team.description),
                              logo=kwargs.get("logo", team.logo),
                              update_time=self.util.get_now())
        return self.__team_detail(team)

    def dismiss_team(self, operator, team_id):
        """Dismiss a team by team leader or hackathon admin

        :rtype: bool
        :return: if dismiss success, return ok. if not ,return bad request.
        """
        team = self.__get_team_by_id(team_id)
        if not team:
            return ok()

        hackathon = team.hackathon
        self.__validate_team_permission(hackathon.id, team, operator)

        members = self.db.find_all_objects_by(UserTeamRel, team_id=team.id, status=TeamMemberStatus.Approved)
        member_users = [m.user for m in members]

        # delete all team members first
        self.db.delete_all_objects_by(UserTeamRel, team_id=team.id)
        self.db.delete_object(team)

        for u in member_users:
            self.create_default_team(hackathon, u)

        return ok()

    def quit_team_forcedly(self, team_id, user):
        """
        The operator(admin or superadmin) forces a user(team leader or other members) to quit a team.
        If the user is the only member of the team, the team will be deleted.
        Else if the user is the leader of a team with several members, the team will be decomposed into several
        new teams.
        Else if the user is not the leader of a team with several members, just the user quits the team.

        :rtype: bool
        :return: if dismiss success, return ok. if not ,return bad request.
        """
        team = self.__get_team_by_id(team_id)
        if not team:
            return not_found("team not exists")

        # here we don't check whether the operator has the permission,

        members = self.db.find_all_objects_by(UserTeamRel, team_id=team.id, status=TeamMemberStatus.Approved)
        if not members or len(members) == 0:
            return not_found("this team doesn't have any members")
        member_users = [m.user for m in members]

        num_team_members = len(member_users)
        hackathon = team.hackathon
        if num_team_members > 1:
            if team.leader_id == user.id:
                self.db.delete_all_objects_by(UserTeamRel, team_id=team.id)
                self.db.delete_object(team)
                for u in member_users:
                    if u.id != user.id:
                        self.create_default_team(hackathon, u)
            else:
                self.db.delete_all_objects_by(UserTeamRel, user_id=user.id, team_id=team_id)
        elif num_team_members == 1:
            self.db.delete_all_objects_by(UserTeamRel, team_id=team.id)
            self.db.delete_object(team)
        else:
            return not_found("this team doesn't have any members")

        return ok()

    def join_team(self, user, team_id):
        """Join a team will create a record on user_team_rel table which status will be 0.

        :type user: User
        :param user: the user to join a team

        :rtype: dict
        :return: if user already joined team or team not exist, return bad request. Else, return a dict of joined
            details.
        """
        if self.db.find_first_object_by(UserTeamRel, user_id=user.id, team_id=team_id):
            return ok("You already joined this team.")

        team = self.__get_team_by_id(team_id)
        if not team:
            return not_found()

        cur_team = self.__get_valid_team_by_user(user.id, team.hackathon_id)
        if cur_team and cur_team.team.user_team_rels.count() > 1:
            return precondition_failed("Team leader cannot join another team for team member count greater than 1")

        if not self.register_manager.is_user_registered(user.id, team.hackathon):
            return precondition_failed("user not registerd")

        candidate = UserTeamRel(join_time=self.util.get_now(),
                                update_time=self.util.get_now(),
                                status=TeamMemberStatus.Init,
                                hackathon_id=team.hackathon.id,
                                user_id=user.id,
                                team_id=team.id)
        self.db.add_object(candidate)
        return candidate.dic()

    def update_team_member_status(self, operator, user_team_rel_id, status):
        """ update user's status on selected team. if current user doesn't have permission, return bad request.
        Else, update user's status

        :type status: int
        :param status: the status of the team member, see TeamMemberStatus in constants.py

        :rtype: bool
        :return: if update success, return ok. if not , return bad request.
        """
        rel = self.db.find_first_object_by(UserTeamRel, id=user_team_rel_id)
        if not rel:
            return not_found()

        team = rel.team
        self.__validate_team_permission(rel.hackathon_id, team, operator)

        if rel.user_id == team.leader_id:
            return precondition_failed("cannot update status of team leader")

        # check if the user is already in this team.
        members = self.db.find_all_objects_by(UserTeamRel, team_id=team.id, status=TeamMemberStatus.Approved)
        if not members or len(members) == 0:
            return not_found("this team doesn't have any members")
        member_users_id = [m.user.id for m in members]
        if rel.user_id in member_users_id:
            return not_found("the user is already in this team.")

        if status == TeamMemberStatus.Approved:
            # disable previous team first
            self.db.delete_all_objects_by(UserTeamRel,
                                          hackathon_id=rel.hackathon_id,
                                          user_id=rel.user_id,
                                          status=TeamMemberStatus.Approved)
            self.db.delete_all_objects_by(Team, hackathon_id=rel.hackathon_id, leader_id=rel.user_id)

            rel.status = TeamMemberStatus.Approved
            rel.update_time = self.util.get_now()
            self.db.commit()
            return ok("approved")
{'fraction_non_alphanumeric': 0.07424860412624243, 'fraction_numerical': 0.0007127865996119273, 'mean_word_length': 2.3154785348562426, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4889324', 'n_tokens_mistral': 7081, 'n_tokens_neox': 6849, 'n_words': 2205}