diff --git a/ceo/cli/groups.py b/ceo/cli/groups.py index b51e27a..e2ec4b5 100644 --- a/ceo/cli/groups.py +++ b/ceo/cli/groups.py @@ -14,6 +14,7 @@ from ceod.transactions.groups import ( DeleteGroupTransaction, ) +import heapq @click.group(short_help='Perform operations on CSC groups/clubs') def groups(): @@ -150,10 +151,75 @@ def delete(group_name): resp = http_delete(f'/api/groups/{group_name}') handle_stream_response(resp, DeleteGroupTransaction.operations) +# compute levenshtein edit distance +def _fuzzy_match(s1, s2): + if len(s1) == 0: + return len(s2) + if len(s2) == 0: + return len(s1) + + edits = [] + for i in range(len(s2) + 1): + edits.append(i) + + for i in range(len(s1)): + corner = i + edits[0] = i + 1 + + for j in range(len(s2)): + upper = edits[j + 1] + if s1[i] == s2[j]: + edits[j + 1] = corner + else: + m = min(corner, upper, edits[j]) + edits[j + 1] = m + 1 + + corner = upper + + return edits[-1] + +# this is needed TRUST ME +class _fuzzy_result: + def __init__(self, string, score): + self.string = string + self.score = score + + def __lt__(self, other): + return self.score < other.score + + def __gt__(self, other): + return self.score > other.score + + def __le__(self, other): + return self.score <= other.score + + def __ge__(self, other): + return self.score >= other.score + + def __eq__(self, other): + return self.score == other.score + + def __ne__(self, other): + return self.score != other.score + @groups.command(short_help='Search for groups') @click.argument('group_name') -def search(group_name): +@click.option('--count', default=10, help='number of results to show') +def search(group_name, count): check_if_in_development() resp = http_get('/api/groups/clubs') result = handle_sync_response(resp) - print(result) + + scores = [] + for i in range(count): + dummy_result = _fuzzy_result(None, -99999) + scores.append(dummy_result) + + for cn in result: + score = -1 * _fuzzy_match(group_name, cn) + result = _fuzzy_result(cn, score) + heapq.heappushpop(scores, result) + + matches = heapq.nlargest(count, scores) + for result in matches: + if result.string: click.echo(result.string)