<commit_before>from collections import namedtuple

import go
from go import Position, place_stone, deduce_groups, parse_sgf_coords as pc
import sgf

def interpret_value(value):
    'Attempt to interpret value as an integer, a float, or a string.'
    try:
        f = float(value)
        i = int(f)
        if f == i:
            return i
        else:
            return f
    except ValueError:
        return value

def sgf_prop(value_list):
    'Converts raw sgf library output to sensible value'
    if value_list is None:
        return None
    if len(value_list) == 1:
        return interpret_value(value_list[0])
    else:
        return map(interpret_value, value_list)

# SGFs have a notion of "add stones" and "play stones".
# Add stones can have arbitrary numbers of either color stone, and is used
# to set up L+D puzzles or handicap stones.
# SGF spec says that you shouldn't resolve captures in an add stone node.
def handle_add_stones(pos, node):
    black_stones_added = node.properties.get('AB', [])
    white_stones_added = node.properties.get('AW', [])
    working_board = pos.board
    for b in black_stones_added:
        working_board = place_stone(working_board, 'B', pc(b))
    for w in white_stones_added:
        working_board = place_stone(working_board, 'W', pc(w))
    return pos._replace(board=working_board, groups=deduce_groups(working_board))

def get_next_move(node):
    if not node.next:
        return None, None
    props = node.next.properties
    if 'W' in props:
        return 'W', props['W']
    else:
        return 'B', props['B']

# Play stones should have just 1 stone. Play is not necessarily alternating;
# sometimes B plays repeatedly at the start in free handicap placement.
# Must look at next node to figure out who was "supposed" to have played.
def handle_play_stones(pos, node):
    props = node.properties<commit_msg>Optimize calls to deduce_groups only when necessary<commit_after>from collections import namedtuple

import go
from go import Position, place_stone, deduce_groups, parse_sgf_coords as pc
import sgf

def interpret_value(value):
    'Attempt to interpret value as an integer, a float, or a string.'
    try:
        f = float(value)
        i = int(f)
        if f == i:
            return i
        else:
            return f
    except ValueError:
        return value

def sgf_prop(value_list):
    'Converts raw sgf library output to sensible value'
    if value_list is None:
        return None
    if len(value_list) == 1:
        return interpret_value(value_list[0])
    else:
        return map(interpret_value, value_list)

# SGFs have a notion of "add stones" and "play stones".
# Add stones can have arbitrary numbers of either color stone, and is used
# to set up L+D puzzles or handicap stones.
# SGF spec says that you shouldn't resolve captures in an add stone node.
def handle_add_stones(pos, node):
    black_stones_added = node.properties.get('AB', [])
    white_stones_added = node.properties.get('AW', [])
    working_board = pos.board
    for b in black_stones_added:
        working_board = place_stone(working_board, 'B', pc(b))
    for w in white_stones_added:
        working_board = place_stone(working_board, 'W', pc(w))
    if black_stones_added or white_stones_added:
        return pos._replace(board=working_board, groups=deduce_groups(working_board))
    else:
        return pos

def get_next_move(node):
    if not node.next:
        return None, None
    props = node.next.properties
    if 'W' in props:
        return 'W', props['W']
    else:
        return 'B', props['B']

# Play stones should have just 1 stone. Play is not necessarily alternating;
# sometimes B plays repeatedly at the start in free handicap placement.
# Must look at next node to figure out who was "supposed" to have played.
def handle_play_stones(pos, node):
    props = node.properties
{'fraction_non_alphanumeric': 0.0804953560371517, 'fraction_numerical': 0.0015479876160990713, 'mean_word_length': 3.150963597430407, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1403234', 'n_tokens_mistral': 1175, 'n_tokens_neox': 1134, 'n_words': 428}