def call_of_the_senate(lines):
    start = "The Senate met at "
    end   = " declared a quorum present."

    _beg = "The roll was called"
    _end = "quorum"

    _roll = getBlocksByTests( lines
                            , lambda ls, l, i:  _beg in l
                            , lambda ils, l, i: _end in l
                            , include_line_numbers=True
                            )

    if not _roll:
        return False
    else:
        rolls, indexes = _roll
        roll = rolls[0]
        index = indexes[0]

    senator_list = parse_vote_name_block( roll[1:len(roll) - 1] )

    return senator_list, index
def find_resolution_votes(lines):
    # TODO: list who moved? it's always present

    # TODO: resolution number, include in chunk, probably easier way is
    # to search backwards from the matched context until resolution
    # number is found, followed by those introducing it.
    # Look for title line
    # Senate Resolution No. \d*

    # Generally begins somewhere:
    #   moved the adoption of the foregoing resolution
    #       - but not containing "The motion prevailed"
    #   The question was taken on the adoption of the resolution.
    #   The role was called
    #   Those who voted

    def begin_test(lines, line, index):
        if index > 10:
            moved = "moved the adoption of the foregoing resolution" in line
            no_prevail = "The motion prevailed" not in line

            a = "The question was taken"
            c = "Those who voted"

            _end = "So the resolution"
            _end_b = "The motion"

            _a, _c = False, False

            if not all([moved, no_prevail]):
                return False

            for _l in lines[index::]:
                if a in _l:
                    _a = True
                if c in _l and _a:
                    _c = True
                if (_end in _l) and (_end_b in _l) and _a and _c:
                    return True

        return False

    # Ends with:
    #   The motion prevailed. So the resolution was adopted.

    def end_test(inner, line, index):
        prevail = "The motion prevailed" in line
        nope    = "The motion did not prevail" in line
        resolution = 'So the resolution' in line
        return (prevail or nope) \
               and resolution

    vote_chunks = getBlocksByTests( lines
                                  , begin_test
                                  , end_test
                                  , include_line_numbers=True
                                  )

    if len(vote_chunks) == 0:
        return False

    return map(process_resolution_vote_chunk, zip(*vote_chunks))
def find_amendment_votes(lines):
    # TODO: list who moved to vote?
    # TODO: there may be another way of introducing multiple amendments
    # for a vote, need to look through for S.F. Nos and H.F. Nos

    def begin_test(lines, line, index):
        if index > 10:
            hf_or_sf        = ('S.F. No.' in line) or ('H.F. No.' in line)
            recommends      = "committee recommends" in line

            with_the        = "with the following" in line
            subject_to      = "subject to the following" in line

            mark_amendments = with_the or subject_to

            if not all([hf_or_sf, recommends, mark_amendments]):
                return False

            a = "The question was taken"
            b = "The roll was called"
            c = "Those who voted"
            _end = "The motion prevailed"
            _end_b = "The motion did not prevail"
            _a, _b, _c = False, False, False

            for _l in lines[index+2::]:
                if 'the amendment was stricken' in _l:
                    return False
                if a in _l:
                    _a = True
                if b in _l and _a:
                    _b = True
                if c in _l and _a and _b:
                    _c = True
                if (_end in _l) or (_end_b in _l) and _a and _b and _c:
                    return True
        return False

    def end_test(inner, line, index):
        # Trick here is that sometimes there's other things coming after
        # this that need to be included, for instance if this line
        # mentions motion status, but the next line mentions another
        # amendment, it's likely to the same bill.
        prevail = "The motion prevailed" in line
        nope    = "The motion did not prevail" in line
        following_amendment = 'moved to amend' in inner[index+1]
        question_taken = 'question was taken' in line
        # Need more accuracy? test preceding S.F. No. / H.F. No. value?
        return (prevail or nope) \
               and not following_amendment \
               and not question_taken

    vote_chunks = getBlocksByTests( lines
                                  , begin_test
                                  , end_test
                                  , include_line_numbers=True
                                  )

    if len(vote_chunks) == 0:
        return False

    return map(process_amendment_vote_chunk, zip(*vote_chunks))
def find_bill_votes(lines):
    """ Find bill votes in the whole text, and return a list of vote
    info.
    """
    # TODO: list who moved to vote?

    def begin_test(lines, line, index):
        """ Two formats to the beginning of a vote on a bill.
             * bill is read with description included
             * bill is read without description
        """
        # TODO: 20100515106 l. 14135 - matching a block which is too big
        # and ends in:
        # So the resolution passed and its title was agreed to.
        # However obviously this keeps going. fix somehow

        first_possibility = False

        if index > 10:
            next_ten = lines[index:index+10]

            hf_or_sf        = ('S.F. No.' in line) or ('H.F. No.' in line)
            was_read        = 'was read' in line
            placed_on       = 'placed' in line

            bill_vote_begin = all([hf_or_sf, was_read, placed_on])

            if bill_vote_begin:
                a = 'question was taken on'
                b = 'roll was called'
                c = 'Those who voted in'
                _a, _b, _c = False, False, False
                for _l in next_ten:
                    if 'passage of the resolution' in _l:
                        first_possibility = False
                        break
                    if a in _l:
                        _a = True
                    if b in _l:
                        _b = True
                    if c in _l:
                        _c = True
                if all([_a, _b, _c]):
                    first_possibility = True

        second_possibility = False

        a_bill_for = ": A bill for an act relating to" in line
        if a_bill_for:
            a = "Was read the third time"
            b = "The question was taken"
            c = "The roll was called"
            d = "Those who voted"
            _a, _b, _c, _d = False, False, False, False

            for _l in lines[index+1::]:
                if ('H.F. No.' in _l) or ('S.F. No.' in _l):
                    second_possibility = False
                    break
                else:
                    if a in _l:
                        _a = True
                    if b in _l and _a:
                        _b = True
                    if c in _l and _b and _a:
                        _c = True
                    if d in _l and _c and _b and _a:
                        _d = True
            if all([_a, _b, _c, _d]):
                second_possibility = True

        return first_possibility or second_possibility

    def end_test(inner, line, index):
        if 'So the bill' in line:
            return True
        return False

    vote_chunks = getBlocksByTests( lines
                                  , begin_test
                                  , end_test
                                  , include_line_numbers=True
                                  )

    if len(vote_chunks) == 0:
        return False

    return map(process_vote_chunk, zip(*vote_chunks))