Scoring Module

Scrabble scoring logic for NHL player names.

The scoring module calculates Scrabble letter values for player names using standard Scrabble point assignments.

Scrabble scoring module.

class nhl_scrabble.scoring.ScrabbleScorer(letter_values=None)[source]

Bases: object

Calculate Scrabble scores for player names using configurable letter values.

This class provides methods to calculate scores based on letter point values. By default, uses standard English Scrabble values, but supports custom scoring systems via the letter_values parameter.

Default letter values (standard Scrabble):
  • 1 point: A, E, I, O, U, L, N, S, T, R

  • 2 points: D, G

  • 3 points: B, C, M, P

  • 4 points: F, H, V, W, Y

  • 5 points: K

  • 8 points: J, X

  • 10 points: Q, Z

Custom scoring systems can be provided via the letter_values parameter, enabling alternative scoring methods (e.g., Wordle scoring, uniform values).

LETTER_VALUES: ClassVar[dict[str, int]] = {'A': 1, 'B': 3, 'C': 3, 'D': 2, 'E': 1, 'F': 4, 'G': 2, 'H': 4, 'I': 1, 'J': 8, 'K': 5, 'L': 1, 'M': 3, 'N': 1, 'O': 1, 'P': 3, 'Q': 10, 'R': 1, 'S': 1, 'T': 1, 'U': 1, 'V': 4, 'W': 4, 'X': 8, 'Y': 4, 'Z': 10}
__init__(letter_values=None)[source]

Initialize the scorer with custom or default letter values.

Parameters:

letter_values (dict[str, int] | None) – Optional custom letter-to-points mapping. If None, uses standard Scrabble values.

Examples

>>> # Standard Scrabble scoring
>>> scorer = ScrabbleScorer()
>>> scorer.calculate_score("ALEX")
11
>>> # Custom scoring (all letters worth 1 point)
>>> uniform_values = {chr(i): 1 for i in range(65, 91)}
>>> scorer = ScrabbleScorer(letter_values=uniform_values)
>>> scorer.calculate_score_custom("ALEX")
4
static calculate_score(name)[source]

Calculate the Scrabble score for a given name using standard values.

This static method provides convenient scoring with default Scrabble letter values. For custom scoring values, create a ScrabbleScorer instance and use the calculate_score_custom() method.

This method uses LRU caching to avoid recomputing scores for duplicate names, which significantly improves performance when processing ~700 NHL players with many duplicate first/last names.

Cache size: 2048 entries (sufficient for all unique name components)

Parameters:

name (str) – The name to score (can include spaces and special characters)

Return type:

int

Returns:

The total Scrabble score (non-letter characters are worth 0 points)

Examples

>>> ScrabbleScorer.calculate_score("ALEX")
11
>>> ScrabbleScorer.calculate_score("Ovechkin")
20
calculate_score_custom(name)[source]

Calculate score using custom letter values configured in this instance.

Use this method when you’ve created a ScrabbleScorer with custom letter values. For default Scrabble scoring, use the static calculate_score() method.

Parameters:

name (str) – The name to score (can include spaces and special characters)

Return type:

int

Returns:

The total score using custom letter values

Examples

>>> uniform_values = {chr(i): 1 for i in range(65, 91)}
>>> scorer = ScrabbleScorer(letter_values=uniform_values)
>>> scorer.calculate_score_custom("ALEX")
4
score_player(player_data, team, division, conference)[source]

Score a player and return a PlayerScore object.

Uses custom letter values if configured, otherwise uses default Scrabble values.

Parameters:
  • player_data (dict[str, Any]) – Dictionary with ‘firstName’ and ‘lastName’ keys containing ‘default’ values

  • team (str) – Team abbreviation

  • division (str) – Division name

  • conference (str) – Conference name

Return type:

PlayerScore

Returns:

PlayerScore object with all scoring information

Examples

>>> scorer = ScrabbleScorer()
>>> player = {"firstName": {"default": "Connor"}, "lastName": {"default": "McDavid"}}
>>> result = scorer.score_player(player, "EDM", "Pacific", "Western")
>>> result.full_score
24
static get_cache_info()[source]

Get cache statistics for the score calculation cache.

Returns:

  • hits: Number of cache hits

  • misses: Number of cache misses

  • maxsize: Maximum cache size

  • currsize: Current cache size

Return type:

dict[str, int]

Examples

>>> info = ScrabbleScorer.get_cache_info()
>>> info['maxsize']
2048
static log_cache_stats()[source]

Log cache statistics for monitoring and performance analysis.

Logs hit rate, total calls, and cache utilization at INFO level.

Return type:

None

static clear_cache()[source]

Clear the score calculation cache.

Useful for testing or when memory needs to be freed.

Return type:

None

Scrabble Scorer

Scrabble scoring logic for player names.

class nhl_scrabble.scoring.scrabble.ScrabbleScorer(letter_values=None)[source]

Bases: object

Calculate Scrabble scores for player names using configurable letter values.

This class provides methods to calculate scores based on letter point values. By default, uses standard English Scrabble values, but supports custom scoring systems via the letter_values parameter.

Default letter values (standard Scrabble):
  • 1 point: A, E, I, O, U, L, N, S, T, R

  • 2 points: D, G

  • 3 points: B, C, M, P

  • 4 points: F, H, V, W, Y

  • 5 points: K

  • 8 points: J, X

  • 10 points: Q, Z

Custom scoring systems can be provided via the letter_values parameter, enabling alternative scoring methods (e.g., Wordle scoring, uniform values).

LETTER_VALUES: ClassVar[dict[str, int]] = {'A': 1, 'B': 3, 'C': 3, 'D': 2, 'E': 1, 'F': 4, 'G': 2, 'H': 4, 'I': 1, 'J': 8, 'K': 5, 'L': 1, 'M': 3, 'N': 1, 'O': 1, 'P': 3, 'Q': 10, 'R': 1, 'S': 1, 'T': 1, 'U': 1, 'V': 4, 'W': 4, 'X': 8, 'Y': 4, 'Z': 10}
__init__(letter_values=None)[source]

Initialize the scorer with custom or default letter values.

Parameters:

letter_values (dict[str, int] | None) – Optional custom letter-to-points mapping. If None, uses standard Scrabble values.

Examples

>>> # Standard Scrabble scoring
>>> scorer = ScrabbleScorer()
>>> scorer.calculate_score("ALEX")
11
>>> # Custom scoring (all letters worth 1 point)
>>> uniform_values = {chr(i): 1 for i in range(65, 91)}
>>> scorer = ScrabbleScorer(letter_values=uniform_values)
>>> scorer.calculate_score_custom("ALEX")
4
static calculate_score(name)[source]

Calculate the Scrabble score for a given name using standard values.

This static method provides convenient scoring with default Scrabble letter values. For custom scoring values, create a ScrabbleScorer instance and use the calculate_score_custom() method.

This method uses LRU caching to avoid recomputing scores for duplicate names, which significantly improves performance when processing ~700 NHL players with many duplicate first/last names.

Cache size: 2048 entries (sufficient for all unique name components)

Parameters:

name (str) – The name to score (can include spaces and special characters)

Return type:

int

Returns:

The total Scrabble score (non-letter characters are worth 0 points)

Examples

>>> ScrabbleScorer.calculate_score("ALEX")
11
>>> ScrabbleScorer.calculate_score("Ovechkin")
20
calculate_score_custom(name)[source]

Calculate score using custom letter values configured in this instance.

Use this method when you’ve created a ScrabbleScorer with custom letter values. For default Scrabble scoring, use the static calculate_score() method.

Parameters:

name (str) – The name to score (can include spaces and special characters)

Return type:

int

Returns:

The total score using custom letter values

Examples

>>> uniform_values = {chr(i): 1 for i in range(65, 91)}
>>> scorer = ScrabbleScorer(letter_values=uniform_values)
>>> scorer.calculate_score_custom("ALEX")
4
score_player(player_data, team, division, conference)[source]

Score a player and return a PlayerScore object.

Uses custom letter values if configured, otherwise uses default Scrabble values.

Parameters:
  • player_data (dict[str, Any]) – Dictionary with ‘firstName’ and ‘lastName’ keys containing ‘default’ values

  • team (str) – Team abbreviation

  • division (str) – Division name

  • conference (str) – Conference name

Return type:

PlayerScore

Returns:

PlayerScore object with all scoring information

Examples

>>> scorer = ScrabbleScorer()
>>> player = {"firstName": {"default": "Connor"}, "lastName": {"default": "McDavid"}}
>>> result = scorer.score_player(player, "EDM", "Pacific", "Western")
>>> result.full_score
24
static get_cache_info()[source]

Get cache statistics for the score calculation cache.

Returns:

  • hits: Number of cache hits

  • misses: Number of cache misses

  • maxsize: Maximum cache size

  • currsize: Current cache size

Return type:

dict[str, int]

Examples

>>> info = ScrabbleScorer.get_cache_info()
>>> info['maxsize']
2048
static log_cache_stats()[source]

Log cache statistics for monitoring and performance analysis.

Logs hit rate, total calls, and cache utilization at INFO level.

Return type:

None

static clear_cache()[source]

Clear the score calculation cache.

Useful for testing or when memory needs to be freed.

Return type:

None

ScrabbleScorer

class nhl_scrabble.scoring.scrabble.ScrabbleScorer(letter_values=None)[source]

Bases: object

Calculate Scrabble scores for player names using configurable letter values.

This class provides methods to calculate scores based on letter point values. By default, uses standard English Scrabble values, but supports custom scoring systems via the letter_values parameter.

Default letter values (standard Scrabble):
  • 1 point: A, E, I, O, U, L, N, S, T, R

  • 2 points: D, G

  • 3 points: B, C, M, P

  • 4 points: F, H, V, W, Y

  • 5 points: K

  • 8 points: J, X

  • 10 points: Q, Z

Custom scoring systems can be provided via the letter_values parameter, enabling alternative scoring methods (e.g., Wordle scoring, uniform values).

LETTER_VALUES: ClassVar[dict[str, int]] = {'A': 1, 'B': 3, 'C': 3, 'D': 2, 'E': 1, 'F': 4, 'G': 2, 'H': 4, 'I': 1, 'J': 8, 'K': 5, 'L': 1, 'M': 3, 'N': 1, 'O': 1, 'P': 3, 'Q': 10, 'R': 1, 'S': 1, 'T': 1, 'U': 1, 'V': 4, 'W': 4, 'X': 8, 'Y': 4, 'Z': 10}
__init__(letter_values=None)[source]

Initialize the scorer with custom or default letter values.

Parameters:

letter_values (dict[str, int] | None) – Optional custom letter-to-points mapping. If None, uses standard Scrabble values.

Examples

>>> # Standard Scrabble scoring
>>> scorer = ScrabbleScorer()
>>> scorer.calculate_score("ALEX")
11
>>> # Custom scoring (all letters worth 1 point)
>>> uniform_values = {chr(i): 1 for i in range(65, 91)}
>>> scorer = ScrabbleScorer(letter_values=uniform_values)
>>> scorer.calculate_score_custom("ALEX")
4
static calculate_score(name)[source]

Calculate the Scrabble score for a given name using standard values.

This static method provides convenient scoring with default Scrabble letter values. For custom scoring values, create a ScrabbleScorer instance and use the calculate_score_custom() method.

This method uses LRU caching to avoid recomputing scores for duplicate names, which significantly improves performance when processing ~700 NHL players with many duplicate first/last names.

Cache size: 2048 entries (sufficient for all unique name components)

Parameters:

name (str) – The name to score (can include spaces and special characters)

Return type:

int

Returns:

The total Scrabble score (non-letter characters are worth 0 points)

Examples

>>> ScrabbleScorer.calculate_score("ALEX")
11
>>> ScrabbleScorer.calculate_score("Ovechkin")
20
calculate_score_custom(name)[source]

Calculate score using custom letter values configured in this instance.

Use this method when you’ve created a ScrabbleScorer with custom letter values. For default Scrabble scoring, use the static calculate_score() method.

Parameters:

name (str) – The name to score (can include spaces and special characters)

Return type:

int

Returns:

The total score using custom letter values

Examples

>>> uniform_values = {chr(i): 1 for i in range(65, 91)}
>>> scorer = ScrabbleScorer(letter_values=uniform_values)
>>> scorer.calculate_score_custom("ALEX")
4
score_player(player_data, team, division, conference)[source]

Score a player and return a PlayerScore object.

Uses custom letter values if configured, otherwise uses default Scrabble values.

Parameters:
  • player_data (dict[str, Any]) – Dictionary with ‘firstName’ and ‘lastName’ keys containing ‘default’ values

  • team (str) – Team abbreviation

  • division (str) – Division name

  • conference (str) – Conference name

Return type:

PlayerScore

Returns:

PlayerScore object with all scoring information

Examples

>>> scorer = ScrabbleScorer()
>>> player = {"firstName": {"default": "Connor"}, "lastName": {"default": "McDavid"}}
>>> result = scorer.score_player(player, "EDM", "Pacific", "Western")
>>> result.full_score
24
static get_cache_info()[source]

Get cache statistics for the score calculation cache.

Returns:

  • hits: Number of cache hits

  • misses: Number of cache misses

  • maxsize: Maximum cache size

  • currsize: Current cache size

Return type:

dict[str, int]

Examples

>>> info = ScrabbleScorer.get_cache_info()
>>> info['maxsize']
2048
static log_cache_stats()[source]

Log cache statistics for monitoring and performance analysis.

Logs hit rate, total calls, and cache utilization at INFO level.

Return type:

None

static clear_cache()[source]

Clear the score calculation cache.

Useful for testing or when memory needs to be freed.

Return type:

None

Calculate Scrabble scores using standard letter values.

Attributes:

  • scrabble_values - Dictionary mapping letters to point values

Letter Values

Standard Scrabble letter point values:

Points

Letters

1

A, E, I, O, U, L, N, S, T, R

2

D, G

3

B, C, M, P

4

F, H, V, W, Y

5

K

8

J, X

10

Q, Z

Constant:

SCRABBLE_VALUES = {
    "A": 1,
    "E": 1,
    "I": 1,
    "O": 1,
    "U": 1,
    "L": 1,
    "N": 1,
    "S": 1,
    "T": 1,
    "R": 1,
    "D": 2,
    "G": 2,
    "B": 3,
    "C": 3,
    "M": 3,
    "P": 3,
    "F": 4,
    "H": 4,
    "V": 4,
    "W": 4,
    "Y": 4,
    "K": 5,
    "J": 8,
    "X": 8,
    "Q": 10,
    "Z": 10,
}

Methods

calculate_score

static ScrabbleScorer.calculate_score(name)[source]

Calculate the Scrabble score for a given name using standard values.

This static method provides convenient scoring with default Scrabble letter values. For custom scoring values, create a ScrabbleScorer instance and use the calculate_score_custom() method.

This method uses LRU caching to avoid recomputing scores for duplicate names, which significantly improves performance when processing ~700 NHL players with many duplicate first/last names.

Cache size: 2048 entries (sufficient for all unique name components)

Parameters:

name (str) – The name to score (can include spaces and special characters)

Return type:

int

Returns:

The total Scrabble score (non-letter characters are worth 0 points)

Examples

>>> ScrabbleScorer.calculate_score("ALEX")
11
>>> ScrabbleScorer.calculate_score("Ovechkin")
20

Calculate Scrabble score for arbitrary text.

Parameters:

  • text - Input text (case-insensitive, non-letters ignored)

Returns:

  • Integer score as sum of letter values

Example:

from nhl_scrabble.scoring import ScrabbleScorer

scorer = ScrabbleScorer()

# Simple word
score = scorer.calculate_score("HELLO")
print(score)  # 8 (H=4, E=1, L=1, L=1, O=1)

# Player name
score = scorer.calculate_score("Ovechkin")
print(score)  # 23 (O=1, V=4, E=1, C=3, H=4, K=5, I=1, N=1)

# Case insensitive
assert scorer.calculate_score("OVECHKIN") == scorer.calculate_score("ovechkin")

score_player

ScrabbleScorer.score_player(player_data, team, division, conference)[source]

Score a player and return a PlayerScore object.

Uses custom letter values if configured, otherwise uses default Scrabble values.

Parameters:
  • player_data (dict[str, Any]) – Dictionary with ‘firstName’ and ‘lastName’ keys containing ‘default’ values

  • team (str) – Team abbreviation

  • division (str) – Division name

  • conference (str) – Conference name

Return type:

PlayerScore

Returns:

PlayerScore object with all scoring information

Examples

>>> scorer = ScrabbleScorer()
>>> player = {"firstName": {"default": "Connor"}, "lastName": {"default": "McDavid"}}
>>> result = scorer.score_player(player, "EDM", "Pacific", "Western")
>>> result.full_score
24

Calculate Scrabble score for a Player object.

Parameters:

  • player - Player object with firstName and lastName

Returns:

  • PlayerScore object with breakdown and total

Example:

from nhl_scrabble.models import Player
from nhl_scrabble.scoring import ScrabbleScorer

player = Player(id=8478402, firstName="Alexander", lastName="Ovechkin", positionCode="LW")

scorer = ScrabbleScorer()
player_score = scorer.score_player(player)

print(f"First name: {player_score.first_score}")  # 22
print(f"Last name: {player_score.last_score}")  # 23
print(f"Total: {player_score.total}")  # 45

Usage Patterns

Basic Scoring:

from nhl_scrabble.scoring import ScrabbleScorer

scorer = ScrabbleScorer()

# Score individual names
scores = {
    "Crosby": scorer.calculate_score("Crosby"),
    "McDavid": scorer.calculate_score("McDavid"),
    "Matthews": scorer.calculate_score("Matthews"),
}

# Find highest scorer
top_name = max(scores, key=scores.get)
print(f"{top_name}: {scores[top_name]} points")

Batch Player Scoring:

from nhl_scrabble.scoring import ScrabbleScorer

scorer = ScrabbleScorer()
player_scores = [scorer.score_player(p) for p in players]

# Sort by total score
player_scores.sort(key=lambda ps: ps.total, reverse=True)

# Display top 10
for i, ps in enumerate(player_scores[:10], 1):
    print(f"{i}. {ps.player.firstName} {ps.player.lastName}: {ps.total}")

Team Aggregation:

from nhl_scrabble.scoring import ScrabbleScorer

scorer = ScrabbleScorer()

# Score all players on a team
team_players = rosters["TOR"]
team_scores = [scorer.score_player(p) for p in team_players]

# Calculate team total
team_total = sum(ps.total for ps in team_scores)
team_avg = team_total / len(team_scores)

print(f"Toronto Maple Leafs:")
print(f"  Total: {team_total}")
print(f"  Average: {team_avg:.1f}")

Special Cases

Non-Letter Characters:

Non-letter characters are ignored:

scorer = ScrabbleScorer()

assert scorer.calculate_score("O'Reilly") == scorer.calculate_score("OReilly")
assert scorer.calculate_score("St. Louis") == scorer.calculate_score("StLouis")
assert scorer.calculate_score("Suter-2") == scorer.calculate_score("Suter")

Empty Strings:

Empty strings score 0:

assert scorer.calculate_score("") == 0
assert scorer.calculate_score("   ") == 0
assert scorer.calculate_score("123") == 0

International Characters:

Only ASCII letters A-Z are scored:

# Accented characters are ignored
score1 = scorer.calculate_score("Koivu")
score2 = scorer.calculate_score("Kóívû")  # Accents ignored
# Scores may differ if letters are different