From 24bfc2c14b3398583c1272ada5062651cc5657a2 Mon Sep 17 00:00:00 2001 From: Ishigh <45936615+Ishigh1@users.noreply.github.com> Date: Sat, 4 May 2024 20:30:18 +0200 Subject: [PATCH 1/7] Fixed text client suggestion --- kvui.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kvui.py b/kvui.py index a1663126cc71..ec601f1912ab 100644 --- a/kvui.py +++ b/kvui.py @@ -285,12 +285,12 @@ def on_touch_down(self, touch): temp = MarkupLabel(text=self.text).markup text = "".join(part for part in temp if not part.startswith(("[color", "[/color]", "[ref=", "[/ref]"))) cmdinput = App.get_running_app().textinput - if not cmdinput.text and " did you mean " in text: - for question in ("Didn't find something that closely matches, did you mean ", - "Too many close matches, did you mean "): + if not cmdinput.text and "did you mean " in text: + for question in ("Didn't find something that closely matches", + "Too many close matches"): if text.startswith(question): - name = Utils.get_text_between(text, question, - "? (") + name = Utils.get_text_between(text, "did you mean '", + "'? (") cmdinput.text = f"!{App.get_running_app().last_autofillable_command} {name}" break elif not cmdinput.text and text.startswith("Missing: "): From 02767fade4c368469934f5ee9e0211c5fccdff9e Mon Sep 17 00:00:00 2001 From: Ishigh <45936615+Ishigh1@users.noreply.github.com> Date: Mon, 6 May 2024 19:26:06 +0200 Subject: [PATCH 2/7] Added a unit test --- MultiServer.py | 14 +++++++++++++ kvui.py | 16 ++++++-------- .../general/test_client_server_interaction.py | 21 +++++++++++++++++++ 3 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 test/general/test_client_server_interaction.py diff --git a/MultiServer.py b/MultiServer.py index f336a523c310..491e9ba74a90 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -1093,6 +1093,20 @@ def get_intended_text(input_text: str, possible_answers) -> typing.Tuple[str, bo f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" +def get_input_text_from_response(text: str, command: str) -> typing.Optional[str]: + if "did you mean " in text: + for question in ("Didn't find something that closely matches", + "Too many close matches"): + if text.startswith(question): + name = Utils.get_text_between(text, "did you mean '", + "'? (") + return f"!{command} {name}" + break + elif text.startswith("Missing: "): + return text.replace("Missing: ", "!hint_location ") + return None + + class CommandMeta(type): def __new__(cls, name, bases, attrs): commands = attrs["commands"] = {} diff --git a/kvui.py b/kvui.py index ec601f1912ab..6732d9d8a797 100644 --- a/kvui.py +++ b/kvui.py @@ -4,6 +4,8 @@ import typing import re +from MultiServer import get_input_text_from_response + if sys.platform == "win32": import ctypes @@ -285,16 +287,10 @@ def on_touch_down(self, touch): temp = MarkupLabel(text=self.text).markup text = "".join(part for part in temp if not part.startswith(("[color", "[/color]", "[ref=", "[/ref]"))) cmdinput = App.get_running_app().textinput - if not cmdinput.text and "did you mean " in text: - for question in ("Didn't find something that closely matches", - "Too many close matches"): - if text.startswith(question): - name = Utils.get_text_between(text, "did you mean '", - "'? (") - cmdinput.text = f"!{App.get_running_app().last_autofillable_command} {name}" - break - elif not cmdinput.text and text.startswith("Missing: "): - cmdinput.text = text.replace("Missing: ", "!hint_location ") + if not cmdinput.text: + input_text = get_input_text_from_response(text, App.get_running_app().last_autofillable_command) + if input_text is not None: + cmdinput.text = input_text Clipboard.copy(text.replace("&", "&").replace("&bl;", "[").replace("&br;", "]")) return self.parent.select_with_touch(self.index, touch) diff --git a/test/general/test_client_server_interaction.py b/test/general/test_client_server_interaction.py new file mode 100644 index 000000000000..03f2c330552f --- /dev/null +++ b/test/general/test_client_server_interaction.py @@ -0,0 +1,21 @@ +import unittest + +from MultiServer import get_intended_text, get_input_text_from_response + + +class TestClient(unittest.TestCase): + def test_autofill_hint_from_fuzzy_hint(self) -> None: + tests = ( + ("item", ["item1", "item2"]), # Multiple close matches + ("itm", ["item1", "item21"]), # No close match, multiple option + ("item", ["item1"]), # No close match, single option + ("item", ["\"item\" 'item' (item)"]), # Testing different special characters + ) + + for input_text, possible_answers in tests: + item_name, usable, response = get_intended_text(input_text, possible_answers) + self.assertFalse(usable, "This test must be updated, it seems get_fuzzy_results behavior changed") + + hint_command = get_input_text_from_response(response, "hint") + self.assertIsNotNone(hint_command, "The response to fuzzy hints is no longer recognized by the hint autofill") + self.assertEqual(hint_command, f"!hint {item_name}", "The hint command autofilled by the response is not correct") \ No newline at end of file From 43a57aff4a5ca128d6dd81d1ae2cf4e3a789a3d7 Mon Sep 17 00:00:00 2001 From: Ishigh <45936615+Ishigh1@users.noreply.github.com> Date: Mon, 13 May 2024 01:41:48 +0200 Subject: [PATCH 3/7] Moved the hint functions to util --- MultiServer.py | 37 +----------------- kvui.py | 2 +- .../general/test_client_server_interaction.py | 2 +- util/server_communication.py | 39 +++++++++++++++++++ 4 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 util/server_communication.py diff --git a/MultiServer.py b/MultiServer.py index 491e9ba74a90..0d0a92fec81a 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -38,6 +38,7 @@ import NetUtils import Utils from Utils import version_tuple, restricted_loads, Version, async_start +from util.server_communication import get_intended_text from NetUtils import Endpoint, ClientStatus, NetworkItem, decode, encode, NetworkPlayer, Permission, NetworkSlot, \ SlotType, LocationStore @@ -1071,42 +1072,6 @@ def json_format_send_event(net_item: NetworkItem, receiving_player: int): "item": net_item} -def get_intended_text(input_text: str, possible_answers) -> typing.Tuple[str, bool, str]: - picks = Utils.get_fuzzy_results(input_text, possible_answers, limit=2) - if len(picks) > 1: - dif = picks[0][1] - picks[1][1] - if picks[0][1] == 100: - return picks[0][0], True, "Perfect Match" - elif picks[0][1] < 75: - return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \ - f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" - elif dif > 5: - return picks[0][0], True, "Close Match" - else: - return picks[0][0], False, f"Too many close matches for '{input_text}', " \ - f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" - else: - if picks[0][1] > 90: - return picks[0][0], True, "Only Option Match" - else: - return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \ - f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" - - -def get_input_text_from_response(text: str, command: str) -> typing.Optional[str]: - if "did you mean " in text: - for question in ("Didn't find something that closely matches", - "Too many close matches"): - if text.startswith(question): - name = Utils.get_text_between(text, "did you mean '", - "'? (") - return f"!{command} {name}" - break - elif text.startswith("Missing: "): - return text.replace("Missing: ", "!hint_location ") - return None - - class CommandMeta(type): def __new__(cls, name, bases, attrs): commands = attrs["commands"] = {} diff --git a/kvui.py b/kvui.py index 6732d9d8a797..7cc977bc2baa 100644 --- a/kvui.py +++ b/kvui.py @@ -4,7 +4,7 @@ import typing import re -from MultiServer import get_input_text_from_response +from util.server_communication import get_input_text_from_response if sys.platform == "win32": import ctypes diff --git a/test/general/test_client_server_interaction.py b/test/general/test_client_server_interaction.py index 03f2c330552f..2cc0845ed276 100644 --- a/test/general/test_client_server_interaction.py +++ b/test/general/test_client_server_interaction.py @@ -1,6 +1,6 @@ import unittest -from MultiServer import get_intended_text, get_input_text_from_response +from util.server_communication import get_intended_text, get_input_text_from_response class TestClient(unittest.TestCase): diff --git a/util/server_communication.py b/util/server_communication.py new file mode 100644 index 000000000000..acbe3732932c --- /dev/null +++ b/util/server_communication.py @@ -0,0 +1,39 @@ +import typing + +import Utils + + +def get_intended_text(input_text: str, possible_answers) -> typing.Tuple[str, bool, str]: + picks = Utils.get_fuzzy_results(input_text, possible_answers, limit=2) + if len(picks) > 1: + dif = picks[0][1] - picks[1][1] + if picks[0][1] == 100: + return picks[0][0], True, "Perfect Match" + elif picks[0][1] < 75: + return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \ + f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" + elif dif > 5: + return picks[0][0], True, "Close Match" + else: + return picks[0][0], False, f"Too many close matches for '{input_text}', " \ + f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" + else: + if picks[0][1] > 90: + return picks[0][0], True, "Only Option Match" + else: + return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \ + f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" + + +def get_input_text_from_response(text: str, command: str) -> typing.Optional[str]: + if "did you mean " in text: + for question in ("Didn't find something that closely matches", + "Too many close matches"): + if text.startswith(question): + name = Utils.get_text_between(text, "did you mean '", + "'? (") + return f"!{command} {name}" + break + elif text.startswith("Missing: "): + return text.replace("Missing: ", "!hint_location ") + return None From 29be1345b454428da24890dad2b367705ecec65e Mon Sep 17 00:00:00 2001 From: Ishigh <45936615+Ishigh1@users.noreply.github.com> Date: Fri, 17 May 2024 22:38:17 +0200 Subject: [PATCH 4/7] Moved get_intended_text and get_input_text_from_response into Utils --- MultiServer.py | 3 +- Utils.py | 34 ++++++++++++++++ kvui.py | 4 +- .../general/test_client_server_interaction.py | 2 +- util/server_communication.py | 39 ------------------- 5 files changed, 37 insertions(+), 45 deletions(-) delete mode 100644 util/server_communication.py diff --git a/MultiServer.py b/MultiServer.py index 0d0a92fec81a..9d6e6426e5f2 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -37,8 +37,7 @@ import NetUtils import Utils -from Utils import version_tuple, restricted_loads, Version, async_start -from util.server_communication import get_intended_text +from Utils import version_tuple, restricted_loads, Version, async_start, get_intended_text from NetUtils import Endpoint, ClientStatus, NetworkItem, decode, encode, NetworkPlayer, Permission, NetworkSlot, \ SlotType, LocationStore diff --git a/Utils.py b/Utils.py index 141b1dc7f8c6..944756935615 100644 --- a/Utils.py +++ b/Utils.py @@ -616,6 +616,40 @@ def get_fuzzy_ratio(word1: str, word2: str) -> float: ) ) +def get_intended_text(input_text: str, possible_answers) -> typing.Tuple[str, bool, str]: + picks = get_fuzzy_results(input_text, possible_answers, limit=2) + if len(picks) > 1: + dif = picks[0][1] - picks[1][1] + if picks[0][1] == 100: + return picks[0][0], True, "Perfect Match" + elif picks[0][1] < 75: + return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \ + f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" + elif dif > 5: + return picks[0][0], True, "Close Match" + else: + return picks[0][0], False, f"Too many close matches for '{input_text}', " \ + f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" + else: + if picks[0][1] > 90: + return picks[0][0], True, "Only Option Match" + else: + return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \ + f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" + + +def get_input_text_from_response(text: str, command: str) -> typing.Optional[str]: + if "did you mean " in text: + for question in ("Didn't find something that closely matches", + "Too many close matches"): + if text.startswith(question): + name = get_text_between(text, "did you mean '", + "'? (") + return f"!{command} {name}" + break + elif text.startswith("Missing: "): + return text.replace("Missing: ", "!hint_location ") + return None def open_filename(title: str, filetypes: typing.Sequence[typing.Tuple[str, typing.Sequence[str]]], suggest: str = "") \ -> typing.Optional[str]: diff --git a/kvui.py b/kvui.py index 7cc977bc2baa..6abfc53582d1 100644 --- a/kvui.py +++ b/kvui.py @@ -4,8 +4,6 @@ import typing import re -from util.server_communication import get_input_text_from_response - if sys.platform == "win32": import ctypes @@ -66,7 +64,7 @@ fade_in_animation = Animation(opacity=0, duration=0) + Animation(opacity=1, duration=0.25) from NetUtils import JSONtoTextParser, JSONMessagePart, SlotType -from Utils import async_start +from Utils import async_start, get_input_text_from_response if typing.TYPE_CHECKING: import CommonClient diff --git a/test/general/test_client_server_interaction.py b/test/general/test_client_server_interaction.py index 2cc0845ed276..9c882fbfa4a6 100644 --- a/test/general/test_client_server_interaction.py +++ b/test/general/test_client_server_interaction.py @@ -1,6 +1,6 @@ import unittest -from util.server_communication import get_intended_text, get_input_text_from_response +from Utils import get_intended_text, get_input_text_from_response class TestClient(unittest.TestCase): diff --git a/util/server_communication.py b/util/server_communication.py deleted file mode 100644 index acbe3732932c..000000000000 --- a/util/server_communication.py +++ /dev/null @@ -1,39 +0,0 @@ -import typing - -import Utils - - -def get_intended_text(input_text: str, possible_answers) -> typing.Tuple[str, bool, str]: - picks = Utils.get_fuzzy_results(input_text, possible_answers, limit=2) - if len(picks) > 1: - dif = picks[0][1] - picks[1][1] - if picks[0][1] == 100: - return picks[0][0], True, "Perfect Match" - elif picks[0][1] < 75: - return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \ - f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" - elif dif > 5: - return picks[0][0], True, "Close Match" - else: - return picks[0][0], False, f"Too many close matches for '{input_text}', " \ - f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" - else: - if picks[0][1] > 90: - return picks[0][0], True, "Only Option Match" - else: - return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \ - f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)" - - -def get_input_text_from_response(text: str, command: str) -> typing.Optional[str]: - if "did you mean " in text: - for question in ("Didn't find something that closely matches", - "Too many close matches"): - if text.startswith(question): - name = Utils.get_text_between(text, "did you mean '", - "'? (") - return f"!{command} {name}" - break - elif text.startswith("Missing: "): - return text.replace("Missing: ", "!hint_location ") - return None From 37cd97c973700421490ea474874dcd493f35b5e4 Mon Sep 17 00:00:00 2001 From: Ishigh <45936615+Ishigh1@users.noreply.github.com> Date: Fri, 17 May 2024 23:06:26 +0200 Subject: [PATCH 5/7] pep 8 --- Utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Utils.py b/Utils.py index 944756935615..5d011a1fb2fc 100644 --- a/Utils.py +++ b/Utils.py @@ -616,6 +616,7 @@ def get_fuzzy_ratio(word1: str, word2: str) -> float: ) ) + def get_intended_text(input_text: str, possible_answers) -> typing.Tuple[str, bool, str]: picks = get_fuzzy_results(input_text, possible_answers, limit=2) if len(picks) > 1: @@ -651,6 +652,7 @@ def get_input_text_from_response(text: str, command: str) -> typing.Optional[str return text.replace("Missing: ", "!hint_location ") return None + def open_filename(title: str, filetypes: typing.Sequence[typing.Tuple[str, typing.Sequence[str]]], suggest: str = "") \ -> typing.Optional[str]: logging.info(f"Opening file input dialog for {title}.") From 15b0aac1c532cf3fac0512ea3c7545067ca724af Mon Sep 17 00:00:00 2001 From: Ishigh <45936615+Ishigh1@users.noreply.github.com> Date: Fri, 17 May 2024 23:30:16 +0200 Subject: [PATCH 6/7] Removed an useless break --- Utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Utils.py b/Utils.py index 5d011a1fb2fc..ccbb14d42c5f 100644 --- a/Utils.py +++ b/Utils.py @@ -647,7 +647,6 @@ def get_input_text_from_response(text: str, command: str) -> typing.Optional[str name = get_text_between(text, "did you mean '", "'? (") return f"!{command} {name}" - break elif text.startswith("Missing: "): return text.replace("Missing: ", "!hint_location ") return None From ee47aa497048e5f88b25b4f5eb99ccd9d225bdf2 Mon Sep 17 00:00:00 2001 From: Ishigh <45936615+Ishigh1@users.noreply.github.com> Date: Fri, 17 May 2024 23:44:13 +0200 Subject: [PATCH 7/7] 120 characters per line limit --- Utils.py | 2 +- test/general/test_client_server_interaction.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Utils.py b/Utils.py index ccbb14d42c5f..fa009a89790e 100644 --- a/Utils.py +++ b/Utils.py @@ -645,7 +645,7 @@ def get_input_text_from_response(text: str, command: str) -> typing.Optional[str "Too many close matches"): if text.startswith(question): name = get_text_between(text, "did you mean '", - "'? (") + "'? (") return f"!{command} {name}" elif text.startswith("Missing: "): return text.replace("Missing: ", "!hint_location ") diff --git a/test/general/test_client_server_interaction.py b/test/general/test_client_server_interaction.py index 9c882fbfa4a6..17de91517409 100644 --- a/test/general/test_client_server_interaction.py +++ b/test/general/test_client_server_interaction.py @@ -17,5 +17,7 @@ def test_autofill_hint_from_fuzzy_hint(self) -> None: self.assertFalse(usable, "This test must be updated, it seems get_fuzzy_results behavior changed") hint_command = get_input_text_from_response(response, "hint") - self.assertIsNotNone(hint_command, "The response to fuzzy hints is no longer recognized by the hint autofill") - self.assertEqual(hint_command, f"!hint {item_name}", "The hint command autofilled by the response is not correct") \ No newline at end of file + self.assertIsNotNone(hint_command, + "The response to fuzzy hints is no longer recognized by the hint autofill") + self.assertEqual(hint_command, f"!hint {item_name}", + "The hint command autofilled by the response is not correct")