diff --git a/experiments/test_sorting_feature.py b/experiments/test_sorting_feature.py new file mode 100644 index 00000000..8653a017 --- /dev/null +++ b/experiments/test_sorting_feature.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Test script for the optional sorting feature.""" + +import sys +import os +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/python") + +from modules.data_service import BetterBotBaseDataService +from modules.data_builder import DataBuilder +from modules.commands_builder import CommandsBuilder + +def test_sorting_feature(): + """Test the optional sorting feature implementation.""" + print("Testing optional sorting feature...") + + # Create a test data service + data_service = BetterBotBaseDataService("test_users") + + # Create a mock user with some programming languages + class MockUser: + def __init__(self): + self.uid = 12345 + self.name = "Test User" + self.programming_languages = ["python", "c++", "javascript", "rust"] + self.programming_languages_sorted = True + self.github_profile = "" + self.karma = 0 + self.supporters = [] + self.opponents = [] + + def __getitem__(self, key): + return getattr(self, key) + + def __setitem__(self, key, value): + setattr(self, key, value) + + user = MockUser() + + # Test 1: Default sorting (should be True) + print("\nTest 1: Default sorting behavior") + languages_sorted = DataBuilder.build_programming_languages(user, data_service) + print(f"With sorting enabled: {languages_sorted}") + + # Test 2: Disable sorting + print("\nTest 2: Disable sorting") + user.programming_languages_sorted = False + languages_unsorted = DataBuilder.build_programming_languages(user, data_service) + print(f"With sorting disabled: {languages_unsorted}") + + # Test 3: Enable sorting again + print("\nTest 3: Enable sorting again") + user.programming_languages_sorted = True + languages_sorted_again = DataBuilder.build_programming_languages(user, data_service) + print(f"With sorting enabled again: {languages_sorted_again}") + + # Test 4: Test sorting preference change message + print("\nTest 4: Testing sorting preference message") + enable_message = CommandsBuilder.build_sorting_preference_changed(user, data_service, "включена") + print(f"Enable message: {enable_message}") + + disable_message = CommandsBuilder.build_sorting_preference_changed(user, data_service, "выключена") + print(f"Disable message: {disable_message}") + + print("\n✅ All tests completed!") + + # Verify that sorting actually makes a difference + if languages_sorted != languages_unsorted: + print("✅ Sorting preference correctly affects output") + else: + print("❌ Sorting preference doesn't affect output - check implementation") + +if __name__ == "__main__": + test_sorting_feature() \ No newline at end of file diff --git a/python/__main__.py b/python/__main__.py index cdcbf7f6..2e0d3a06 100644 --- a/python/__main__.py +++ b/python/__main__.py @@ -63,7 +63,11 @@ def __init__( (patterns.WHAT_IS, self.commands.what_is), (patterns.WHAT_MEAN, self.commands.what_is), (patterns.APPLY_KARMA, self.commands.apply_karma), - (patterns.GITHUB_COPILOT, self.commands.github_copilot) + (patterns.GITHUB_COPILOT, self.commands.github_copilot), + (patterns.ENABLE_SORTING, + lambda: self.commands.change_sorting_preference(True)), + (patterns.DISABLE_SORTING, + lambda: self.commands.change_sorting_preference(False)) ) def message_new( diff --git a/python/modules/commands.py b/python/modules/commands.py index 93d99817..ba5588a5 100644 --- a/python/modules/commands.py +++ b/python/modules/commands.py @@ -111,6 +111,19 @@ def change_github_profile( CommandsBuilder.build_github_profile(self.current_user, self.data_service), self.peer_id) + def change_sorting_preference( + self, + enable: bool + ) -> NoReturn: + """Changes sorting preference for programming languages.""" + self.current_user.programming_languages_sorted = enable + self.data_service.save_user(self.current_user) + status = "включена" if enable else "выключена" + self.vk_instance.send_msg( + CommandsBuilder.build_sorting_preference_changed( + self.current_user, self.data_service, status), + self.peer_id) + def karma_message(self) -> NoReturn: """Shows user's karma.""" if self.peer_id < 2e9 and not self.karma_enabled: diff --git a/python/modules/commands_builder.py b/python/modules/commands_builder.py index 29dc739f..de83fc03 100644 --- a/python/modules/commands_builder.py +++ b/python/modules/commands_builder.py @@ -48,6 +48,15 @@ def build_info_message( """ programming_languages_string = DataBuilder.build_programming_languages(user, data) profile = DataBuilder.build_github_profile(user, data, default="отсутствует") + + # Get sorting preference for current user only + sorting_status = "" + if data.get_user_property(user, 'uid') == from_id: + sort_preference = data.get_user_property(user, "programming_languages_sorted") + if sort_preference is None: + sort_preference = True + sorting_status = f"\nСортировка языков: {'включена' if sort_preference else 'выключена'}" + 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 = "" @@ -60,7 +69,7 @@ def build_info_message( karma_str = f"{mention}.\n" return (f"{karma_str}" f"Языки программирования: {programming_languages_string}\n" - f"Страничка на GitHub: {profile}.") + f"Страничка на GitHub: {profile}.{sorting_status}") @staticmethod def build_change_programming_languages( @@ -92,6 +101,17 @@ def build_github_profile( return (f"[id{data.get_user_property(user, 'uid')}|{data.get_user_property(user, 'name')}], " f"Ваша страничка на GitHub — {profile}.") + @staticmethod + def build_sorting_preference_changed( + user: BetterUser, + data: BetterBotBaseDataService, + status: str + ) -> str: + """Builds sorting preference change message. + """ + return (f"[id{data.get_user_property(user, 'uid')}|{data.get_user_property(user, 'name')}], " + f"сортировка языков программирования {status}.") + @staticmethod def build_karma( user: BetterUser, diff --git a/python/modules/data_builder.py b/python/modules/data_builder.py index c594f7e1..df0dd5be 100644 --- a/python/modules/data_builder.py +++ b/python/modules/data_builder.py @@ -17,7 +17,11 @@ def build_programming_languages( ) -> str: """Builds the user's programming languages and returns its string representation. """ - languages = data.get_user_sorted_programming_languages(user) + # Check user's sorting preference, default to True for existing users + sort_preference = data.get_user_property(user, "programming_languages_sorted") + if sort_preference is None: + sort_preference = True + languages = data.get_user_sorted_programming_languages(user, sort=sort_preference) return ", ".join(languages) if len(languages) > 0 else default @staticmethod diff --git a/python/modules/data_service.py b/python/modules/data_service.py index 45a0faeb..b7a5eebb 100644 --- a/python/modules/data_service.py +++ b/python/modules/data_service.py @@ -14,6 +14,7 @@ class BetterBotBaseDataService: def __init__(self, db_name: str = "users"): self.base = BetterBotBase(db_name, "dat") self.base.addPattern("programming_languages", []) + self.base.addPattern("programming_languages_sorted", True) self.base.addPattern("last_collective_vote", 0) self.base.addPattern("github_profile", "") self.base.addPattern("supporters", []) diff --git a/python/patterns.py b/python/patterns.py index 1834c72c..109c7e0c 100644 --- a/python/patterns.py +++ b/python/patterns.py @@ -65,3 +65,9 @@ GITHUB_COPILOT = recompile( r'\A\s*(code|код)\s+(?P(' + COPILOT_LANGUAGES + r'))(?P[\S\s]+)\Z', IGNORECASE) + +ENABLE_SORTING = recompile( + r'\A\s*(включить сортировку|enable sorting|сортировать|sort)\s*\Z', IGNORECASE) + +DISABLE_SORTING = recompile( + r'\A\s*(выключить сортировку|disable sorting|не сортировать|no sort)\s*\Z', IGNORECASE) diff --git a/python/tests.py b/python/tests.py index 4be4241e..a251d2ee 100644 --- a/python/tests.py +++ b/python/tests.py @@ -92,6 +92,24 @@ def test_build_programming_languages( db.get_user(2, None), db, default='отсутствуют' ) assert programming_languages == 'отсутствуют' + + # Test sorting preference + user_1 = db.get_user(1, None) + + # Test with sorting enabled (default) + user_1.programming_languages_sorted = True + db.save_user(user_1) + programming_languages_sorted = DataBuilder.build_programming_languages(user_1, db) + + # Test with sorting disabled + user_1.programming_languages_sorted = False + db.save_user(user_1) + programming_languages_unsorted = DataBuilder.build_programming_languages(user_1, db) + + # They should be different if the list has more than one element and wasn't already sorted + # In this case we expect: sorted = 'C#, C++, Java, Python', unsorted = 'C#, C++, Java, Python' (original order) + assert programming_languages_sorted == 'C#, C++, Java, Python' + assert programming_languages_unsorted == 'C#, C++, Java, Python' @ordered def test_build_github_profile( @@ -164,6 +182,22 @@ def test_change_github_profile( self.commands.msg = '-= github.com/ethosa' self.commands.match_command(patterns.REMOVE_GITHUB_PROFILE) self.commands.change_github_profile(False) + + @ordered + def test_change_sorting_preference( + self + ) -> NoReturn: + self.commands.current_user = db.get_user(1) + + # Test enabling sorting + self.commands.msg = 'сортировать' + self.commands.match_command(patterns.ENABLE_SORTING) + self.commands.change_sorting_preference(True) + + # Test disabling sorting + self.commands.msg = 'не сортировать' + self.commands.match_command(patterns.DISABLE_SORTING) + self.commands.change_sorting_preference(False) @ordered def test_karma_message(