Beispiel #1
0
def hard_coding(val_list):
    message = ("Please show code that makes the computer extract "
               "the value from the dictionary.")
    code = "hard_code"
    tldr = "Printing raw value"
    # Pattern 1 possibility
    matches = find_matches("print(__exp__)")
    for match in matches:
        __exp__ = match["__exp__"]
        value = __exp__.value
        if value in val_list:
            return explain_r(message, code, label=tldr)

    # Pattern 2 possibility
    matches = find_matches("__exp__\n" "print(_var_)")
    for match in matches:
        __exp__ = match["__exp__"]
        _var_ = match["_var_"]
        submatches = __exp__.find_matches("_var_ = __exp2__")
        for submatch in submatches:
            __exp2__ = submatch["__exp2__"]
            value = __exp2__.value
            if value in val_list:
                return explain_r(message, code, label=tldr)
    return False
Beispiel #2
0
def prevent_advanced_iteration():
    message = "You should not use a <code>while</code> loop to solve this problem."
    code = "while_usage"
    label = "Usage of <code>while</code>"
    ast = parse_program()
    if ast.find_all('While'):
        explain_r(message, code, label=label)
    prevent_builtin_usage([
        'sum', 'map', 'filter', 'reduce', 'len', 'max', 'min', 'max', 'sorted',
        'all', 'any', 'getattr', 'setattr', 'eval', 'exec', 'iter'
    ])
Beispiel #3
0
def prevent_builtin_usage(function_names):
    message = "You cannot use the builtin function <code>{}</code>."
    code = "builtin_use"
    label = "Builtin Usage"
    # Prevent direction calls
    ast = parse_program()
    all_calls = ast.find_all('Call')
    for a_call in all_calls:
        if a_call.func.ast_name == 'Name':
            if a_call.func.id in function_names:
                explain_r(message.format(a_call.func.id), code, label=label)
                return a_call.func.id
    return None
Beispiel #4
0
def wrong_debug_10_6():
    """
    Should be on change feedback as opposed to on-run
    Returns:
    """
    message = "This is not one of the two changes needed. Undo the change and try again."
    code = "debug_10.6"
    tldr = "At least one unnecessary change"
    matches = find_matches('quakes = earthquakes.get("location.depth","(None)","")\n'
                           'quakes_in_miles = []\n'
                           'for quake in _list1_:\n'
                           '    _list2_.append(quake * 0.62)\n'
                           'plt.hist(quakes_in_miles)\n'
                           'plt.xlabel("Depth in Miles")\n'
                           'plt.ylabel("Number of Earthquakes")\n'
                           'plt.title("Distribution of Depth in Miles of Earthquakes")\n'
                           'plt.show()')
    for match in matches:
        name1 = match["_list1_"][0].ast_node.id
        name2 = match["_list2_"][0].ast_node.id
        master_list = ["quake", "quakes", "quakes_in_miles"]
        if (name1 in master_list and name2 in master_list and
                name1 != "quakes_in_miles" and name2 != "quakes" and
                (name1 != "quake" or name2 != "quake")):
            return False
    return explain_r(message, code, label=tldr)
Beispiel #5
0
def wrong_filter_problem_atl1_10_5():
    """
    find pattern where expression is equal to _item_*0.62 and
    where the condition is not equivalent to _expr_ > 10
    Returns:
    """
    message = "You are not correctly filtering out values from the list."
    code = "filt_alt1_10.5"
    tldr = "Incorrect Filter Statement"
    matches = find_matches("for _item_ in ___:\n"
                           "    if __cond__:\n"
                           "        _list_.append(__expr__)")
    if matches:
        for match in matches:
            _item_ = match["_item_"][0].astNode
            __cond__ = match["__cond__"]
            __expr__ = match["__expr__"]
            # matches02 = __expr__.find_matches("{0!s}*0.62".format(_item_.id))
            matches02 = __expr__.find_matches("_item_*0.62")
            if matches02:
                for match02 in matches02:
                    if (__cond__.has(_item_) and
                            not __cond__.numeric_logic_check(0.1, "item > 16.1290322580645")):
                        return explain_r(message, code, label=tldr)
    return False
Beispiel #6
0
def wrong_should_be_summing():
    """
    std_ast = parse_program()
    for_loops = std_ast.find_all('For')
    for loop in for_loops:
        assignments = loop.find_all('Assign')
        for assignment in assignments:
            binops = assignment.find_all('BinOp')
            for binop in binops:
                if binop.has(1) and binop.op == 'Add':
                    explain('This problem asks for the total of all the values in the list not the number of items in '
                            'the list.<br><br><i>(not_sum)<i></br>')
    """
    message = "This problem asks for the total of all the values in the list not the number of items in the list."
    code = "not_sum"
    tldr = "Counting instead of summing"
    matches = find_matches("for _item_ in ___:\n"
                           "    __expr__")
    if matches:
        for match in matches:
            __expr__ = match["__expr__"]
            submatches = __expr__.find_matches("___ = 1 + ___", )
            if submatches:
                return explain_r(message, code, label=tldr)
    return False
Beispiel #7
0
def missing_key(keys):
    """
    Checks if student is missing a key

    TODO: Should be good if run AFTER the var_instead_of_key check, although it doesn't appear to catch a key that's
       been assigned as the value of an unused variable.
    :param keys: list of keys
    :type keys: list of Str
    :return: Feedback String
    :rtype: Str
    """
    message = "You seem to be missing the following dictionary key(s):<ul>{}</ul>"
    code = "miss_key"
    tldr = "Missing necessary keys"
    key_list = ""
    first = False
    for key in keys:
        matches = find_matches("\"{}\"".format(key))
        if not matches:
            if not first:
                key_list += ", "
            key_list += '<li><code>"' + key + '"</code></li>'
    if key_list != "":
        return explain_r(message.format(key_list), code, label=tldr)
    return False
Beispiel #8
0
def histogram_argument_not_list():
    """

    Name: histogram_argument_not_list
    Pattern:
       plt.hist(<argument>)
    Where type(<argument>) is not "list"

    Feedback: Making a histogram requires a list; <argument> is not a list.


    Returns:
    """
    message = "Making a histogram requires a list; <code>{0!s}</code> is not a list."
    code = "hist_arg_not_list"
    tldr = "Making Histogram from Non-list"
    matches = find_matches("plt.hist(_argument_)")
    if matches:
        for match in matches:
            _argument_ = match["_argument_"].astNode
            if not _argument_.get_data_state(
            ) or not _argument_.get_data_state().was_type('list'):
                return explain_r(message.format(_argument_.id),
                                 code,
                                 label=tldr)
    return False
Beispiel #9
0
def histogram_wrong_list():
    """

    Name: histogram_wrong_list
    Pattern:

    for ___ in ___:
       <target>.append(___)
    plt.hist(<list>)

    where name(<target>) != name(<list>)

    Feedback: The list created in the iteration is not the list being used to create the histogram.

    Returns:
    """
    message = "The list created in the iteration is not the list being used to create the histogram."
    code = "histo_wrong_list"
    tldr = "Plotting Wrong List"
    matches = find_matches("for ___ in ___:\n"
                           "    __expr__\n"
                           "plt.hist(_list_)")
    if matches:
        for match in matches:
            _list_ = match["_list_"].astNode
            __expr__ = match["__expr__"]
            submatches = __expr__.find_matches("_list_.append(___)")
            if submatches:
                return False
        return explain_r(message, code, label=tldr)
    return False
Beispiel #10
0
def key_order_unchained(keys):
    message = "It looks like you aren't using the correct keys, or the correct key order. Double check your data map."
    code = "key_order_u"
    tldr = "Wrong key order"

    construct = None
    find_chain = ""
    for a_slice in range(len(keys)):
        find_chain += "_var{a2}_ = _var{a1}_[__str{a1}__]\n".format(
            a2=a_slice + 1, a1=a_slice)
    if find_match(find_chain):
        construct = ""
        count = 0
        for key in keys:
            construct += "_var{a2}_ = _var{a1}_['{key}']\n".format(a2=count +
                                                                   1,
                                                                   a1=count,
                                                                   key=key)
            count += 1

    if construct:
        matches = find_matches(construct)
        if not matches:
            return explain_r(message, code, label=tldr)
    return False
Beispiel #11
0
def missing_addition_slot_empty():
    """
    std_ast = parse_program()
    assignments = std_ast.find_all('Assign')
    for assignment in assignments:
        # left = assignment.target
        right = assignment.value
        binOp = right.find_all('BinOp')
        if len(binOp) == 1:
            binOp = binOp[0]
            if binOp.op == 'Add':
                if binOp.left.ast_name == 'Name' and binOp.right.ast_name == 'Name':
                    if binOp.left.id == '___' or binOp.right.id == '___':
                        explain('You must fill in the empty slot in the addition.<br><br><i>(add_empty)<i></br>')
                        return True
    return False
    Returns:
    """
    message = "You must fill in the empty slot in the addition."
    code = "add_empty"
    tldr = "Addition Blank"
    matches = find_matches("___ + _item_")
    if matches:
        for match in matches:
            _item_ = match["_item_"][0]
            if _item_.id == "___":
                return explain_r(message, code, tldr)
    return False
Beispiel #12
0
def key_order(keys):
    # TODO: Is it possible to run this test after confirming (through other tests) that there are no unused keys and
    #  that all keys used are the correct keys, such that the feedback message can explicitly address JUST the case of
    #  wrong order?
    message = "It looks like you aren't using the correct keys, or the correct key order. Double check your data map."
    code = "key_order_c"
    tldr = "Wrong key order"

    construct = None
    # Assemble chain of dictionary slicing
    find_chain = "_var_"
    for a_slice in range(len(keys)):
        find_chain += "[__str{}__]".format(a_slice)
    # If we find a chain of dictionary accesses
    if find_match(find_chain):
        # Assemble a new match pattern using the provided key order
        construct = "_var_"
        for key in keys:
            construct += "['{}']".format(key)

    if construct:
        # check if we have a set of keys of the proper order
        matches = find_matches(construct)
        if not matches:
            return explain_r(message, code, label=tldr)
    return False
Beispiel #13
0
def wrong_cannot_sum_list():
    """

    std_ast = parse_program()
    for_loops = std_ast.find_all('For')
    for loop in for_loops:
        list_prop = loop.iter
        assignments = loop.find_all('Assign')
        for assignment in assignments:
            binops = assignment.find_all('BinOp')
            for binop in binops:
                if binop.has(list_prop) and binop.op == 'Add':
                    explain('Addition can only be done with a single value at a time, not with an entire list at one'
                            ' time.<br><br><i>(sum_list)<i></br>')
    Returns:
    """
    message = 'Addition can only be done with a single value at a time, not with an entire list at one'
    code = "sum_list"
    tldr = "Cannot Sum a List"
    matches = find_matches("for ___ in _list_ :\n"
                           "    __expr__")
    if matches:
        for match in matches:
            _list_ = match["_list_"][0]
            __expr__ = match["__expr__"]
            # submatches = __expr__.find_matches("___ = ___ + {}".format(_list_.id), )
            submatches = __expr__.find_matches("___ = ___ + _list_")
            if submatches:
                return explain_r(message, code, label=tldr)
    return False
Beispiel #14
0
def missing_counting_list():
    """
    std_ast = parse_program()
    has_count = False
    for_loops = std_ast.find_all('For')
    if len(for_loops) > 0:
        for loop in for_loops:
            assignments = loop.find_all('Assign')
            if len(assignments) < 1:
                continue
            for assignment in assignments:
                binops = assignment.find_all('BinOp')
                if len(binops) < 1:
                    continue
                lhs = assignment.target
                for binop in binops:
                    if binop.has(lhs) and binop.has(1) and binop.op == 'Add':
                        has_count = True
    if not has_count:
        explain('Count the total number of items in the list using iteration.<br><br><i>(miss_count_list)<i></br>')
    Returns:
    """
    message = 'Count the total number of items in the list using iteration.'
    code = "miss_count_list"
    tldr = "Missing Count in Iteration"
    matches = find_matches("for _item_ in ___:\n"
                           "    __expr__")
    if matches:
        for match in matches:
            __expr__ = match["__expr__"]
            submatches = __expr__.find_matches("_sum_ = _sum_ + 1", )
            if submatches:
                return False
    return explain_r(message, code, label=tldr)
Beispiel #15
0
def wrong_duplicate_var_in_add():
    message = "You are adding the same variable twice; you need two different variables in your addition."
    code = "dup_var"
    tldr = "Duplicate Division"
    match = find_match("_item_ + _item_")
    if match:
        return explain_r(message, code, label=tldr)
    return False
Beispiel #16
0
def plot_group_error(output=None, plots=None):
    if output is None:
        output = get_output()
    if plots is None:
        plots = get_plots()
    if len(plots) > 1:
        explain_r('You should only be plotting one thing!', "print_one", "Multiple Calls to plot")
        return True
    elif len(plots) == 0:
        explain_r('The algorithm is plotting an empty list. Check your logic.', 'blank_plot', "Blank Plot")
        return True
    elif output:
        explain('You should be plotting, not printing!', 'printing', "Printing instead of Plotting")
        return True
    elif len(plots[0]['data']) != 1:
        explain('You should only be plotting one thing!', 'one_plot', "Too Many Plots")
        return True
def missing_iterator_initialization():
    message1 = "The slot to hold a list in the iteration is empty."
    code1 = "no_iter_init-blank"
    tldr1 = "Iteration Variable is Blank"

    message2 = "The variable <code>{0!s}</code> is in the list slot of the iteration but is not a list."
    code2 = "no_iter_init"
    tldr2 = "Iteration Variable is Not a List"

    match = find_match("for ___ in _list_:\n    pass")
    if match:
        _list_ = match["_list_"].astNode
        if _list_.id == "___":
            return explain_r(message1, code1, label=tldr1)
        elif not data_state(_list_).was_type('list'):
            return explain_r(message2.format(_list_.id), code2, label=tldr2)
    return False
Beispiel #18
0
def wrong_accumulator_initialization_9_2():
    message = ("The variable to hold the total value of the rainfall amounts "
               "(<code>rainfall_count</code>) is not initialized properly.")
    code = "accu_init_9.2"
    tldr = "Incorrect Initialization"
    if not find_matches("rainfall_count = 0"):
        return explain_r(message, code, label=tldr)
    return False
Beispiel #19
0
def missing_no_print():
    message = "Program does not output anything."
    code = "no_print"
    tldr = "Missing Output"
    prints = find_match('print(___)', cut=True)
    if not prints:
        return explain_r(message, code, label=tldr)
    return False
Beispiel #20
0
def wrong_list_initialization_9_2():
    message = "The list of rainfall amounts (<code>rainfall_list</code>) is not initialized properly."
    code = "list_init_9.2"
    tldr = "Incorrect List Initialization"
    matches = find_matches('rainfall_list = weather.get("Data.Precipitation","Station.Location","Blacksburg, VA")')
    if not matches:
        return explain_r(message, code, label=tldr)
    return False
Beispiel #21
0
def app_assign():
    message = ("Appending modifies the list, so unlike addition,"
               " an assignment statement is not needed when using append.")
    code = "app_asgn"

    matches = find_matches("_sum_ = _sum_.append(__exp__)")
    if matches:
        return explain_r(message, code)
    return False
Beispiel #22
0
def wrong_iteration_body_9_1():
    message = "The addition of each rainfall amount to the total rainfall is not in the correct place."
    code = "iter_body_9.1"
    tldr = "Accumulation Statement Misplaced or Missing"
    matches = find_matches("for _item_ in _list_:\n"
                           "    rainfall_sum = ___")
    if not matches:
        return explain_r(message, code, label=tldr)
    return False
Beispiel #23
0
def wrong_accumulator_initialization_9_1():
    message = ("The variable to hold the total value of the rainfall amounts (<code>rainfall_sum</code>) "
               "is not initialized properly.")
    code = "accu_init_9.1"
    tldr = "Incorrect Accumulation Variable initialization"
    match = find_match("rainfall_sum = 0")
    if not match:
        return explain_r(message, code, label=tldr)
    return False
Beispiel #24
0
def col_dict():
    message = "When using multiple keys, each key should have it's own set of brackets."
    code = "col_dict"
    tldr = "Improper Dictionary Access"

    matches = find_matches("_var_[__str1__: __str2__]")
    if matches:
        return explain_r(message, code, label=tldr)
    return False
Beispiel #25
0
def wrong_iteration_body_8_3():
    message = "The addition of each episode length to the total length is not in the correct place."
    code = "iter_body_8.3"
    tldr = "Accumulation Misplaced"
    match = find_match("for _item_ in _list_:\n"
                       "    sum_length = ___ + ___\n")
    if not match:
        return explain_r(message, code, label=tldr)
    return False
Beispiel #26
0
def wrong_for_inside_if():
    message = "The iteration should not be inside the decision block."
    code = "for_in_if"
    tldr = "For inside if"
    match = find_match("if ___:\n"
                       "    for ___ in ___:\n"
                       "        pass")
    if match:
        return explain_r(message, code, label=tldr)
    return False
Beispiel #27
0
def wrong_list_is_constant_8_2():
    message = 'You must set <code>shoppping_cart</code> to a list of values not to a single number.'
    code = "list_is_const_8.2"
    tldr = "Shopping Cart not set to list"
    matches = find_matches("shopping_cart = __expr__")
    for match in matches:
        __expr__ = match["__expr__"]
        if __expr__.ast_name == "Num":
            return explain_r(message, code, label=tldr)
    return False
Beispiel #28
0
def func_filter(keys):
    message = "Please do not modify the function call to retrieve the data."
    code = "func_filt"
    tldr = "Attempting to filter using fetch"
    matches = find_matches("_var_.get_weather(__str__)")
    for match in matches:
        __str__ = match["__str__"]
        if __str__.value in keys:  # TODO: Relies on .value returning id for Name nodes
            return explain_r(message, code, label=tldr)
    return False
Beispiel #29
0
def miss_dict_acc():
    message = (
        "You are missing something that looks like a dictionary access. "
        "In this unit, you should be using dictionary access")
    code = "miss_acc"
    tldr = "Missing Dictionary Access"

    if not find_matches("_var_[__str1__]"):
        return explain_r(message, code, label=tldr)
    return False
def missing_target_slot_empty():
    message = "You must fill in the empty slot in the iteration."
    code = "target_empty"
    tldr = "Missing Iteration Variable"
    match = find_match("for _item_ in ___:\n    pass")
    if match:
        _item_ = match["_item_"].astNode
        if _item_.id == "___":
            return explain_r(message, code, label=tldr)
    return False