Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions experiments/test_logic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
"""
Simple test to verify the logic of top position calculation.
This test mimics the logic without importing the actual modules.
"""

def calculate_real_karma(user, POSITIVE_VOTES_PER_KARMA=3, NEGATIVE_VOTES_PER_KARMA=2):
"""Mock implementation of calculate_real_karma"""
base_karma = user["karma"]
up_votes = len(user["supporters"]) / POSITIVE_VOTES_PER_KARMA
down_votes = len(user["opponents"]) / NEGATIVE_VOTES_PER_KARMA
return base_karma + up_votes - down_votes

def get_users_sorted_by_karma(mock_users):
"""Mock implementation of get_users_sorted_by_karma"""
# Filter to only chat members (all in our mock)
users = mock_users.copy()

# Sort by real karma
users.sort(key=lambda u: calculate_real_karma(u), reverse=True)
return users

def get_user_top_position(user, mock_users):
"""Mock implementation of get_user_top_position"""
users = get_users_sorted_by_karma(mock_users)
users = [u for u in users if
(u["karma"] != 0) or
("programming_languages" in u and len(u["programming_languages"]) > 0)]

user_uid = user["uid"]
for index, ranked_user in enumerate(users):
if ranked_user["uid"] == user_uid:
return index + 1 # 1-based position
return 0 # User not found in ranking

def test_top_position():
"""Test the top position logic"""
# Mock users with different karma values
mock_users = [
{"uid": 1, "karma": 100, "supporters": [], "opponents": [], "name": "User1", "programming_languages": ["Python"]},
{"uid": 2, "karma": 80, "supporters": [101, 102], "opponents": [], "name": "User2", "programming_languages": ["JavaScript"]},
{"uid": 3, "karma": 60, "supporters": [], "opponents": [201], "name": "User3", "programming_languages": ["Java"]},
{"uid": 4, "karma": 40, "supporters": [301], "opponents": [401, 402, 403], "name": "User4", "programming_languages": ["C++"]},
{"uid": 5, "karma": 20, "supporters": [], "opponents": [], "name": "User5", "programming_languages": ["Go"]},
{"uid": 6, "karma": 0, "supporters": [], "opponents": [], "name": "User6", "programming_languages": []}, # Should be excluded
]

print("Mock users with calculated real karma:")
sorted_users = get_users_sorted_by_karma(mock_users)
for i, user in enumerate(sorted_users):
real_karma = calculate_real_karma(user)
print(f" {i+1}. {user['name']} (uid: {user['uid']}) - karma: {user['karma']}, real karma: {real_karma:.1f}")

print("\nFiltered users for ranking (excluding users with 0 karma and no languages):")
filtered_users = [u for u in sorted_users if
(u["karma"] != 0) or
("programming_languages" in u and len(u["programming_languages"]) > 0)]
for i, user in enumerate(filtered_users):
print(f" {i+1}. {user['name']} (uid: {user['uid']})")

print("\nTesting position calculation:")
for user in mock_users:
position = get_user_top_position(user, mock_users)
print(f" {user['name']} (uid: {user['uid']}) -> position: {position}")

if __name__ == "__main__":
test_top_position()
95 changes: 95 additions & 0 deletions experiments/test_top_position.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env python3
"""
Test script to verify the top position functionality works correctly.
"""
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'python'))

# Mock the necessary dependencies for testing
class MockBetterUser(dict):
pass

class MockVk:
def get_members_ids(self, peer_id):
return [1, 2, 3, 4, 5] # Mock member IDs

class MockDataService:
def get_user_property(self, user, prop):
return user[prop]

def get_user_sorted_programming_languages(self, user):
return user.get("programming_languages", [])

def get_users(self, other_keys=None, sort_key=None, reverse_sort=True):
# Mock users data with different karma values
mock_users = [
{"uid": 1, "karma": 100, "supporters": [], "opponents": [], "name": "User1", "programming_languages": ["Python"], "github_profile": "user1"},
{"uid": 2, "karma": 80, "supporters": [], "opponents": [], "name": "User2", "programming_languages": ["JavaScript"], "github_profile": "user2"},
{"uid": 3, "karma": 60, "supporters": [], "opponents": [], "name": "User3", "programming_languages": ["Java"], "github_profile": "user3"},
{"uid": 4, "karma": 40, "supporters": [], "opponents": [], "name": "User4", "programming_languages": ["C++"], "github_profile": "user4"},
{"uid": 5, "karma": 20, "supporters": [], "opponents": [], "name": "User5", "programming_languages": ["Go"], "github_profile": "user5"},
]

if sort_key:
mock_users.sort(key=sort_key, reverse=reverse_sort)

return mock_users

# Import the modules after setting up mocks
from modules.data_builder import DataBuilder
from modules.commands_builder import CommandsBuilder

def test_get_user_top_position():
"""Test that the get_user_top_position function works correctly"""
vk_instance = MockVk()
data_service = MockDataService()

# Test user with highest karma (should be position 1)
user1 = MockBetterUser({"uid": 1, "karma": 100, "supporters": [], "opponents": [], "name": "User1", "programming_languages": ["Python"], "github_profile": "user1"})
position1 = DataBuilder.get_user_top_position(user1, vk_instance, data_service, 2000000001)
print(f"User1 (karma 100) position: {position1}")

# Test user with middle karma (should be position 3)
user3 = MockBetterUser({"uid": 3, "karma": 60, "supporters": [], "opponents": [], "name": "User3", "programming_languages": ["Java"], "github_profile": "user3"})
position3 = DataBuilder.get_user_top_position(user3, vk_instance, data_service, 2000000001)
print(f"User3 (karma 60) position: {position3}")

# Test user with lowest karma (should be position 5)
user5 = MockBetterUser({"uid": 5, "karma": 20, "supporters": [], "opponents": [], "name": "User5", "programming_languages": ["Go"], "github_profile": "user5"})
position5 = DataBuilder.get_user_top_position(user5, vk_instance, data_service, 2000000001)
print(f"User5 (karma 20) position: {position5}")

# Test non-existent user (should be position 0)
user_fake = MockBetterUser({"uid": 999, "karma": 50, "supporters": [], "opponents": [], "name": "FakeUser", "programming_languages": ["Python"], "github_profile": "fake"})
position_fake = DataBuilder.get_user_top_position(user_fake, vk_instance, data_service, 2000000001)
print(f"Fake user position: {position_fake}")

def test_build_info_message():
"""Test that the build_info_message includes top position"""
vk_instance = MockVk()
data_service = MockDataService()

user2 = MockBetterUser({"uid": 2, "karma": 80, "supporters": [], "opponents": [], "name": "User2", "programming_languages": ["JavaScript"], "github_profile": "user2"})

# Test with karma enabled and group chat
message = CommandsBuilder.build_info_message(
user2, data_service, 2, True, vk_instance, 2000000001
)
print("Info message with top position:")
print(message)
print()

# Test without karma
message_no_karma = CommandsBuilder.build_info_message(
user2, data_service, 2, False, vk_instance, 2000000001
)
print("Info message without karma:")
print(message_no_karma)

if __name__ == "__main__":
print("Testing top position functionality...")
test_get_user_top_position()
print()
test_build_info_message()
print("All tests completed!")
3 changes: 2 additions & 1 deletion python/modules/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ def info_message(self) -> NoReturn:
"""Sends user info"""
self.vk_instance.send_msg(
CommandsBuilder.build_info_message(
self.user, self.data_service, self.from_id, self.karma_enabled),
self.user, self.data_service, self.from_id, self.karma_enabled,
self.vk_instance, self.peer_id),
self.peer_id)

def update_command(self) -> NoReturn:
Expand Down
22 changes: 17 additions & 5 deletions python/modules/commands_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,38 @@ def build_info_message(
user: BetterUser,
data: BetterBotBaseDataService,
from_id: int,
karma: bool
karma: bool,
vk_instance=None,
peer_id: int = 0
) -> str:
"""Builds info message.

Arguments:
- {user} - selected user;
- {data} - data service;
- {peer_id} - chat ID;
- {karma} - is karma enabled in chat.
- {from_id} - user ID requesting info;
- {karma} - is karma enabled in chat;
- {vk_instance} - VK instance for getting top position;
- {peer_id} - chat ID for getting top position.
"""
programming_languages_string = DataBuilder.build_programming_languages(user, data)
profile = DataBuilder.build_github_profile(user, data, default="отсутствует")
mention = f"[id{data.get_user_property(user, 'uid')}|{data.get_user_property(user, 'name')}]"
is_self = data.get_user_property(user, 'uid') == from_id
karma_str: str = ""

# Get top position if in group chat and karma enabled
top_position_str = ""
if karma and peer_id > 2e9 and vk_instance:
position = DataBuilder.get_user_top_position(user, vk_instance, data, peer_id)
if position > 0:
top_position_str = f" (место в топе: {position})"

if karma:
if is_self:
karma_str = f"{mention}, Ваша карма - {DataBuilder.build_karma(user, data)}.\n"
karma_str = f"{mention}, Ваша карма - {DataBuilder.build_karma(user, data)}{top_position_str}.\n"
else:
karma_str = f"Карма {mention} - {DataBuilder.build_karma(user, data)}.\n"
karma_str = f"Карма {mention} - {DataBuilder.build_karma(user, data)}{top_position_str}.\n"
else:
karma_str = f"{mention}.\n"
return (f"{karma_str}"
Expand Down
25 changes: 25 additions & 0 deletions python/modules/data_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,31 @@ def get_users_sorted_by_name(
users.reverse()
return users

@staticmethod
def get_user_top_position(
user: BetterUser,
vk_instance: Vk,
data: BetterBotBaseDataService,
peer_id: int
) -> int:
"""Gets user's position in the top ranking (1-based index).

Returns:
- Position number (1 for first place, 2 for second, etc.)
- 0 if user is not found in ranking
"""
users = DataBuilder.get_users_sorted_by_karma(vk_instance, data, peer_id)
users = [u for u in users if
(u["karma"] != 0) or
("programming_languages" in u and len(u["programming_languages"]) > 0)
]

user_uid = user["uid"]
for index, ranked_user in enumerate(users):
if ranked_user["uid"] == user_uid:
return index + 1 # 1-based position
return 0 # User not found in ranking

@staticmethod
def calculate_real_karma(
user: BetterUser,
Expand Down
Loading