Exemplo n.º 1
0
def calculate(data: str) -> str:
    """Calculates ISBN Check Digits.

    Args:
        data: A string of characters representing an ISBN code without the check digit

    Returns:
        str: The check digit that was missing

    Examples:
        >>> from checkdigit import isbn
        >>> # ISBN-10
        >>> isbn.calculate("043942089")
        'X'
        >>> # ISBN-13
        >>> isbn.calculate("978-1-86197-876")
        '9'
    """
    data = cleanse(data)

    if len(data) == 9:
        # ISBN 10 (without the check digit)
        # Multiply first digit by 10, second by 9, ... and take the sum
        total_sum = sum(
            int(digit) * weight for digit, weight in zip(data, range(10, 0, -1))
        )
        return convert(11 - (total_sum % 11))
    # elif not required since return above (and makes pylint happy)
    if len(data) == 12:
        # ISBN weights is 1 for odd positions and 3 for even
        # Since there are 12 digits, multiply weights by 6
        weights = (1, 3) * 6
        # Multiply each digit by its weight
        total_sum = sum(int(digit) * weight for digit, weight in zip(data, weights))
        # Return final check digit and type of barcode
        return convert(10 - (total_sum % 10))
    return "Invalid"
Exemplo n.º 2
0
def calculate10(data: str) -> str:
    """Calculates ISBN-10 Check Digit.

    Args:
        data: A string of 9 characters

    Returns:
        str: The check digit that was missing
    """
    data = cleanse(data)
    # Multiply first digit by 10, second by 9, ... and take the sum
    total_sum = sum(
        int(digit) * weight for digit, weight in zip(data, range(10, 0, -1))
    )
    return convert(11 - (total_sum % 11))
Exemplo n.º 3
0
def calculate10(data: str) -> str:
    """Calculates ISBN-10 Check Digit.

    Args:
        data: A string of 9 characters

    Returns:
        str: The check digit that was missing
    """
    data = cleanse(data)
    total_sum = 0
    multiply_counter = 10
    for item in data:
        total_sum += int(item) * multiply_counter
        multiply_counter -= 1  # Multiplies first digit by 10, second by 9...
    check_digit = 11 - (total_sum % 11)
    return convert(check_digit)
Exemplo n.º 4
0
def calculate13(data: str, barcode: str = "isbn") -> str:
    """Calculates ISBN-13 Check Digit.

    Args:
        data: A string of 12 characters
        barcode: The type of code (either isbn or upc)

    Returns:
        str: The check digit that was missing
    """
    data = cleanse(data)
    # ISBN weights is 1 for odd positions and 3 for even
    # The opposite is true for upc
    weights = (1, 3) * 6 if barcode == "isbn" else (3, 1) * 6
    # Multiply each digit by its weight
    total_sum = sum(int(digit) * weight for digit, weight in zip(data, weights))
    # Return final check digit and type of barcode
    return convert(10 - (total_sum % 10), barcode)
Exemplo n.º 5
0
def missing(data: str) -> str:
    """Calculates a missing digit in a GS1 Code.

    This method works for all fixed length numeric GS1 data structures
    (including GDTI, GLN, GRAI, etc.) that require a check digit.

    Args:
        data: A string of characters representing a full ISBN code
            with a question mark representing a missing character

    Returns:
        str: The missing value that should've been where the question mark was

    """
    data = cleanse(data)
    for poss_digit in range(10):  # Brute Force the 10 options
        option = convert(poss_digit)
        # tests it with the generated number
        # If this fails, the next number is tried
        if validate(data.replace("?", option)):
            return option
    return "Invalid"
Exemplo n.º 6
0
def missing(data: str) -> str:
    """Calculates a missing digit in an ISBN Code.

    Args:
        data: A string of characters representing a full ISBN code
            with a question mark representing a missing character

    Returns:
        str: The missing value that should've been where the question mark was

    """
    data = cleanse(data)
    for poss_digit in range(11):  # Brute Force the 11 options
        option = convert(poss_digit)
        # Depending on the size of the data, the relevant validating function
        # tests it with the generated number
        # If this fails, the next number is tried
        if (len(data) == 10 and validate10(data.replace("?", option))) or (
            len(data) == 13 and validate13(data.replace("?", option))
        ):
            return option
    return "Invalid"
Exemplo n.º 7
0
def calculate(data: str) -> str:
    """Calculates GS1 Check Digit.

    This method works for all fixed length numeric GS1 data structures
    (including GDTI, GLN, GRAI, etc.) that require a check digit.

    Args:
        data: A string of characters

    Returns:
        str: The check digit that was missing
    """
    data = cleanse(data)
    data = data[::-1]  # Reverse the barcode, as last digit is always multiplied by 3
    total_sum = 0
    for index, value in enumerate(data):
        if index % 2 == 0:
            total_sum += int(value) * 3
        else:
            total_sum += int(value)
    next_multiple_of_ten = int(math.ceil(total_sum / 10.0)) * 10
    check_digit = next_multiple_of_ten - total_sum
    return convert(check_digit, "gs1")
Exemplo n.º 8
0
def calculate13(data: str, barcode: str = "isbn") -> str:
    """Calculates ISBN-13 Check Digit.

    Args:
        data: A string of 12 characters
        barcode: The type of code (either isbn or upc)

    Returns:
        str: The check digit that was missing
    """
    data = cleanse(data)
    mod_number = 0 if barcode == "isbn" else 1
    total_sum = 0
    position_counter = 1  # 1 based indexing for data
    for item in data:
        digit = int(item)
        if position_counter % 2 == mod_number:
            total_sum += digit * 3  # Multiplies by 3 if position is even
        else:
            total_sum += digit
        position_counter += 1
    final_value = 10 - (total_sum % 10)
    return convert(final_value, barcode)