|
|
|
|
|
import os |
|
|
import sys |
|
|
import pytest |
|
|
|
|
|
|
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) |
|
|
|
|
|
from wrdler.modules.constants import HF_API_TOKEN |
|
|
from wrdler.modules.storage import gen_full_url, _get_json_from_repo, HF_REPO_ID, SHORTENER_JSON_FILE |
|
|
from wrdler.word_loader import compute_word_difficulties, compute_word_difficulties2, compute_word_difficulties3 |
|
|
|
|
|
|
|
|
if HF_API_TOKEN: |
|
|
os.environ["HF_API_TOKEN"] = HF_API_TOKEN |
|
|
|
|
|
|
|
|
sample_words = [] |
|
|
|
|
|
def test_compare_difficulty_functions_for_challenge(capsys): |
|
|
""" |
|
|
Compare compute_word_difficulties, compute_word_difficulties2, and compute_word_difficulties3 |
|
|
for all users in a challenge identified by short_id. |
|
|
""" |
|
|
global sample_words |
|
|
|
|
|
|
|
|
short_id = "hDjsB_dl" |
|
|
|
|
|
|
|
|
status, full_url = gen_full_url( |
|
|
short_url=short_id, |
|
|
repo_id=HF_REPO_ID, |
|
|
json_file=SHORTENER_JSON_FILE |
|
|
) |
|
|
|
|
|
if status != "success_retrieved_full" or not full_url: |
|
|
print( |
|
|
f"Could not resolve short id '{short_id}'. " |
|
|
f"Status: {status}. " |
|
|
f"Check repo '{HF_REPO_ID}' and mapping file '{SHORTENER_JSON_FILE}'." |
|
|
) |
|
|
captured = capsys.readouterr() |
|
|
assert "Could not resolve short id" in captured.out |
|
|
assert not full_url, "full_url should be empty/None on failure" |
|
|
print("settings.json was not found or could not be resolved.") |
|
|
return |
|
|
|
|
|
print(f"✓ Resolved short id '{short_id}' to full URL: {full_url}") |
|
|
|
|
|
|
|
|
url_parts = full_url.split("/resolve/main/") |
|
|
assert len(url_parts) == 2, f"Invalid full URL format: {full_url}" |
|
|
file_path = url_parts[1] |
|
|
|
|
|
|
|
|
settings = _get_json_from_repo(HF_REPO_ID, file_path, repo_type="dataset") |
|
|
assert settings, "Failed to download or parse settings.json" |
|
|
print(f"✓ Downloaded settings.json") |
|
|
|
|
|
|
|
|
assert "challenge_id" in settings |
|
|
assert "wordlist_source" in settings |
|
|
assert "users" in settings |
|
|
|
|
|
wordlist_source = settings.get("wordlist_source", "wordlist.txt") |
|
|
users = settings.get("users", []) |
|
|
|
|
|
print(f"\nChallenge ID: {settings['challenge_id']}") |
|
|
print(f"Wordlist Source: {wordlist_source}") |
|
|
print(f"Number of Users: {len(users)}") |
|
|
|
|
|
|
|
|
|
|
|
words_dir = os.path.join(os.path.dirname(__file__), "..", "battlewords", "words") |
|
|
wordlist_path = os.path.join(words_dir, wordlist_source) |
|
|
|
|
|
|
|
|
if not os.path.exists(wordlist_path): |
|
|
print(f"⚠ Wordlist '{wordlist_source}' not found, using 'classic.txt' as fallback") |
|
|
wordlist_path = os.path.join(words_dir, "classic.txt") |
|
|
|
|
|
assert os.path.exists(wordlist_path), f"Wordlist file not found: {wordlist_path}" |
|
|
print(f"✓ Using wordlist: {wordlist_path}") |
|
|
|
|
|
|
|
|
print("\n" + "="*80) |
|
|
print("DIFFICULTY COMPARISON BY USER") |
|
|
print("="*80) |
|
|
|
|
|
all_results = [] |
|
|
|
|
|
for user_idx, user in enumerate(users, 1): |
|
|
user_name = user.get("name", f"User {user_idx}") |
|
|
word_list = user.get("word_list", []) |
|
|
sample_words += word_list |
|
|
|
|
|
if not word_list: |
|
|
print(f"\n[{user_idx}] {user_name}: No words assigned, skipping") |
|
|
continue |
|
|
|
|
|
print(f"\n[{user_idx}] {user_name}") |
|
|
print(f" Words: {len(word_list)} words") |
|
|
print(f" Sample: {', '.join(word_list[:5])}{'...' if len(word_list) > 5 else ''}") |
|
|
|
|
|
|
|
|
total_diff1, difficulties1 = compute_word_difficulties(wordlist_path, word_list) |
|
|
total_diff2, difficulties2 = compute_word_difficulties2(wordlist_path, word_list) |
|
|
total_diff3, difficulties3 = compute_word_difficulties3(wordlist_path, word_list) |
|
|
|
|
|
print(f"\n Function 1 (compute_word_difficulties):") |
|
|
print(f" Total Difficulty: {total_diff1:.4f}") |
|
|
print(f" Words Processed: {len(difficulties1)}") |
|
|
|
|
|
print(f"\n Function 2 (compute_word_difficulties2):") |
|
|
print(f" Total Difficulty: {total_diff2:.4f}") |
|
|
print(f" Words Processed: {len(difficulties2)}") |
|
|
|
|
|
print(f"\n Function 3 (compute_word_difficulties3):") |
|
|
print(f" Total Difficulty: {total_diff3:.4f}") |
|
|
print(f" Words Processed: {len(difficulties3)}") |
|
|
|
|
|
|
|
|
if difficulties1 and difficulties2 and difficulties3: |
|
|
avg_diff1 = total_diff1 / len(difficulties1) |
|
|
avg_diff2 = total_diff2 / len(difficulties2) |
|
|
avg_diff3 = total_diff3 / len(difficulties3) |
|
|
|
|
|
print(f"\n Comparison:") |
|
|
print(f" Average Difficulty (Func1): {avg_diff1:.4f}") |
|
|
print(f" Average Difficulty (Func2): {avg_diff2:.4f}") |
|
|
print(f" Average Difficulty (Func3): {avg_diff3:.4f}") |
|
|
print(f" Difference (Func1 vs Func2): {abs(avg_diff1 - avg_diff2):.4f}") |
|
|
print(f" Difference (Func1 vs Func3): {abs(avg_diff1 - avg_diff3):.4f}") |
|
|
print(f" Difference (Func2 vs Func3): {abs(avg_diff2 - avg_diff3):.4f}") |
|
|
|
|
|
|
|
|
all_results.append({ |
|
|
"user_name": user_name, |
|
|
"word_count": len(word_list), |
|
|
"total_diff1": total_diff1, |
|
|
"total_diff2": total_diff2, |
|
|
"total_diff3": total_diff3, |
|
|
"difficulties1": difficulties1, |
|
|
"difficulties2": difficulties2, |
|
|
"difficulties3": difficulties3, |
|
|
}) |
|
|
|
|
|
|
|
|
print("\n" + "="*80) |
|
|
print("OVERALL SUMMARY") |
|
|
print("="*80) |
|
|
|
|
|
if all_results: |
|
|
total1_sum = sum(r["total_diff1"] for r in all_results) |
|
|
total2_sum = sum(r["total_diff2"] for r in all_results) |
|
|
total3_sum = sum(r["total_diff3"] for r in all_results) |
|
|
total_words = sum(r["word_count"] for r in all_results) |
|
|
|
|
|
print(f"\nTotal Users Analyzed: {len(all_results)}") |
|
|
print(f"Total Words Across All Users: {total_words}") |
|
|
print(f"\nAggregate Total Difficulty:") |
|
|
print(f" Function 1: {total1_sum:.4f}") |
|
|
print(f" Function 2: {total2_sum:.4f}") |
|
|
print(f" Function 3: {total3_sum:.4f}") |
|
|
print(f" Difference (Func1 vs Func2): {abs(total1_sum - total2_sum):.4f}") |
|
|
print(f" Difference (Func1 vs Func3): {abs(total1_sum - total3_sum):.4f}") |
|
|
print(f" Difference (Func2 vs Func3): {abs(total2_sum - total3_sum):.4f}") |
|
|
|
|
|
|
|
|
assert all(r["difficulties1"] for r in all_results), "Function 1 failed for some users" |
|
|
assert all(r["difficulties2"] for r in all_results), "Function 2 failed for some users" |
|
|
assert all(r["difficulties3"] for r in all_results), "Function 3 failed for some users" |
|
|
|
|
|
print("\n✓ All tests passed!") |
|
|
else: |
|
|
print("\n⚠ No users with words found in this challenge") |
|
|
|
|
|
|
|
|
def test_compare_difficulty_functions_with_classic_wordlist(): |
|
|
""" |
|
|
Test all three difficulty functions using the classic.txt wordlist |
|
|
with a sample set of words. |
|
|
""" |
|
|
global sample_words |
|
|
|
|
|
words_dir = os.path.join(os.path.dirname(__file__), "..", "battlewords", "words") |
|
|
wordlist_path = os.path.join(words_dir, "classic.txt") |
|
|
|
|
|
if not os.path.exists(wordlist_path): |
|
|
pytest.skip(f"classic.txt not found at {wordlist_path}") |
|
|
|
|
|
|
|
|
if not sample_words: |
|
|
sample_words = ["ABLE", "ACID", "AREA", "ARMY", "BEAR", "BOWL", "CAVE", "COIN", "ECHO", "GOLD"] |
|
|
|
|
|
print("\n" + "="*80) |
|
|
print("TESTING WITH CLASSIC.TXT WORDLIST") |
|
|
print("="*80) |
|
|
print(f"Sample Words: {', '.join(sample_words)}") |
|
|
|
|
|
|
|
|
total_diff1, difficulties1 = compute_word_difficulties(wordlist_path, sample_words) |
|
|
total_diff2, difficulties2 = compute_word_difficulties2(wordlist_path, sample_words) |
|
|
total_diff3, difficulties3 = compute_word_difficulties3(wordlist_path, sample_words) |
|
|
|
|
|
print(f"\nFunction compute_word_difficulties Results:") |
|
|
print(f" Total Difficulty: {total_diff1:.4f}") |
|
|
for word in sample_words: |
|
|
if word in difficulties1: |
|
|
print(f" {word}: {difficulties1[word]:.4f}") |
|
|
|
|
|
print(f"\nFunction compute_word_difficulties2 Results:") |
|
|
print(f" Total Difficulty: {total_diff2:.4f}") |
|
|
for word in sample_words: |
|
|
if word in difficulties2: |
|
|
print(f" {word}: {difficulties2[word]:.4f}") |
|
|
|
|
|
print(f"\nFunction compute_word_difficulties3 Results:") |
|
|
print(f" Total Difficulty: {total_diff3:.4f}") |
|
|
for word in sample_words: |
|
|
if word in difficulties3: |
|
|
print(f" {word}: {difficulties3[word]:.4f}") |
|
|
|
|
|
|
|
|
assert len(difficulties1) == len(set(sample_words)), "Function 1 didn't process all words" |
|
|
assert len(difficulties2) == len(set(sample_words)), "Function 2 didn't process all words" |
|
|
assert len(difficulties3) == len(set(sample_words)), "Function 3 didn't process all words" |
|
|
assert total_diff1 > 0, "Function 1 total difficulty should be positive" |
|
|
assert total_diff2 > 0, "Function 2 total difficulty should be positive" |
|
|
assert total_diff3 > 0, "Function 3 total difficulty should be positive" |
|
|
|
|
|
print("\n✓ Classic wordlist test passed!") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
pytest.main(["-s", "-v", __file__]) |