Example #1
0
    def get(self, community_id):

        user = UserModel.find_by_username(get_jwt_identity())
        community = CommunityModel.find_by_id(community_id)

        if not community:
            abort(400, message=COMMUNIY_DOESNT_EXIST)

        if user.id not in [u.id for u in community.users]:
            abort(401, message=UNAUTHORIZED)

        return TourModel.find_finished_by_community(community_id), 200
def get_community_statistic(community_id, from_datetime, to_datetime):
    community: CommunityModel = CommunityModel.find_by_id(community_id)

    if not community:
        abort(404, message=COMMUNIY_DOESNT_EXIST)

    user = UserModel.find_by_username(get_jwt_identity())

    community_member_ids = [m.id for m in community.users]
    if user.id not in community_member_ids:
        abort(401, message=UNAUTHORIZED)

    statistic = CommunityStatisticModel()
    statistic.community = community
    statistic.statistic_start = from_datetime
    statistic.statistic_end = to_datetime

    all_tours = TourModel.find_finished_by_community(community_id)
    all_costs = RefuelModel.find_by_community(community_id)
    km_per_user_dict = {}
    costs_per_user_dict = {}
    for user in community.users:
        km_per_user_dict[user.id] = KmPerUserModel()
        km_per_user_dict[user.id].user = user
        statistic.km_per_user.append(km_per_user_dict[user.id])
        costs_per_user_dict[user.id] = CostsPerUserModel()
        costs_per_user_dict[user.id].user = user
        statistic.costs_per_user.append(costs_per_user_dict[user.id])
    for tour in all_tours:
        if from_datetime <= tour.end_time.astimezone(pytz.utc) <= to_datetime:
            tour_km = tour.end_km - tour.start_km
            km_per_user_dict[tour.owner_id].km += tour_km
            # Divide km of passengers
            all_passengers_ids = [tour.owner_id] + [
                passenger.id for passenger in tour.passengers
            ]
            for passenger_id in all_passengers_ids:
                km_per_user_dict[
                    passenger_id].km_accounted_for_passengers += tour_km / len(
                        all_passengers_ids)
    for cost in all_costs:
        if from_datetime <= cost.time_created.astimezone(
                pytz.utc) <= to_datetime:
            costs_per_user_dict[cost.owner_id].costs += cost.costs

    return statistic
Example #3
0
    def post(self, id):
        community = CommunityModel.find_by_id(id)
        user = UserModel.find_by_username(get_jwt_identity())

        if not community:
            abort(404, message=COMMUNIY_DOESNT_EXIST)

        if user.id not in [u.id for u in community.users]:
            abort(401, message=UNAUTHORIZED)

        if TourModel.find_running_by_community(id):
            abort(400, message=CANT_CREATE_PAYOFF_WHEN_UNFINISHED_TOURS_EXIST)

        # tours: List[TourModel] = TourModel.find_finished_and_open_by_community(id)
        # refuels: List[RefuelModel] = RefuelModel.find_open_by_community(id)
        tours: List[TourModel] = TourModel.find_finished_by_community(id)
        refuels: List[RefuelModel] = RefuelModel.find_by_community(id)

        if not [t for t in tours if t.is_open
                ] and not [r for r in refuels if r.is_open]:
            abort(400,
                  message=CANT_CREATE_PAYOFF_WITHOUT_NEW_REFUELS_AND_TOURS)

        # Calculate some basic statistics
        total_km = sum(map(lambda t: t.end_km - t.start_km, tours))
        km_per_user = {}
        for tour in tours:
            involved_users = [tour.owner] + tour.passengers
            km_per_involved_user = (tour.end_km -
                                    tour.start_km) / len(involved_users)
            for involved_user in involved_users:
                if involved_user.id not in km_per_user:
                    km_per_user[involved_user.id] = 0
                km_per_user[involved_user.id] += km_per_involved_user
        # If there is a user from refuels missing, he has zero costs/kms
        for refuel in refuels:
            if refuel.owner.id not in km_per_user:
                km_per_user[refuel.owner.id] = 0
        km_fraction_per_user = {}
        for user_id, km in km_per_user.items():
            km_fraction_per_user[user_id] = km / total_km

        # Create reference user id to user dict
        user_dictionary = OrderedDict()
        for tour in tours:
            if tour.owner.id not in user_dictionary:
                user_dictionary[tour.owner.id] = tour.owner
            for passenger in tour.passengers:
                if passenger.id not in user_dictionary:
                    user_dictionary[passenger.id] = passenger
        for refuel in refuels:
            if refuel.owner.id not in user_dictionary:
                user_dictionary[refuel.owner.id] = refuel.owner

        # Create debt matrix (debtee on y axis, recipient on x axis)
        debt_matrix = np.zeros((len(user_dictionary), len(user_dictionary)))
        for refuel in refuels:
            recipient_position = list(user_dictionary.keys()).index(
                refuel.owner.id)
            for user_id in user_dictionary.keys():
                if user_id != refuel.owner.id:
                    debtee_position = list(
                        user_dictionary.keys()).index(user_id)
                    debt_amount = refuel.costs * km_fraction_per_user[user_id]
                    debt_matrix[debtee_position,
                                recipient_position] += float(debt_amount)

        # Include already created debts from previous payoffs
        debts = DebtModel.find_by_community(id)
        for debt in debts:
            recipient_position = list(user_dictionary.keys()).index(
                debt.recepient_id)
            debtee_position = list(user_dictionary.keys()).index(
                debt.debtee_id)
            debt_matrix[debtee_position,
                        recipient_position] -= float(debt.amount)

        # Simplify debt matrix
        debt_matrix = simplify_debt_matrix(debt_matrix)

        # Create and persist payoff
        payoff = PayoffModel()
        payoff.community_id = id
        payoff.persist()

        # Create and persist debt objects
        for i in range(debt_matrix.shape[0]):
            for j in range(debt_matrix.shape[0]):
                if debt_matrix[i, j] != 0:
                    debt = DebtModel()
                    debt.debtee = list(user_dictionary.values())[i]
                    debt.recepient = list(user_dictionary.values())[j]
                    debt.amount = round(debt_matrix[i, j], 2)
                    debt.payoff_id = payoff.id
                    debt.community_id = id
                    debt.persist()

        # If there is no resulting debt in the payoff, the payoff is settled
        if not np.any(debt_matrix != 0):
            payoff.is_settled = True

        # Set open tours to non open and add payoff id
        for tour in tours:
            if tour.is_open:
                tour.is_open = False
                tour.payoff_id = payoff.id
                tour.persist()

        # Set open refuels to non open and add payoff id
        for refuel in refuels:
            if refuel.is_open:
                refuel.is_open = False
                refuel.payoff_id = payoff.id
                refuel.persist()

        return payoff, 201