Example #1
0
def check_chart(state, extra_msg=None):
    solution_chart = find_chart(state.solution_data["charts"], state.sct_range)
    if len(state.student_data["charts"]) == 0:
        state.report(f"Please create a chart near `{state.sct_range}`.")
    student_chart = find_chart(state.student_data["charts"], state.sct_range)
    student_chart_anchor = row_columns_to_range(find_chart_anchor(student_chart))

    solution_chart_type = infer_chart_type(solution_chart)

    chart_type_msg = (
        f"The chart type of the chart at `{student_chart_anchor}` is not correct."
    )

    if Dispatcher().select(f"spec.{solution_chart_type}", student_chart) is None:
        state.report(chart_type_msg)
    elif solution_chart_type == "basicChart":
        chart_type_path = "spec.basicChart.chartType"
        student_chart_type = Dispatcher().select(chart_type_path, student_chart)
        detailed_solution_chart_type = Dispatcher().select(
            chart_type_path, solution_chart
        )
        if student_chart_type != detailed_solution_chart_type:
            state.report(chart_type_msg)

    return state.to_child(
        student_data=student_chart["spec"],
        solution_data=solution_chart["spec"],
        append_message=f"In the chart at `{student_chart_anchor}`, ",
        node_name=solution_chart_type,
    )
Example #2
0
def manhattan_distance_to_chart(chart, sct_range):
    anchor_cell = find_chart_anchor(chart)
    x = anchor_cell["start_column"]
    y = anchor_cell["start_row"]
    sct_range_as_row_columns = range_to_row_columns(sct_range)
    x_sct = Dispatcher().select("start_column", sct_range_as_row_columns, fallback=0)
    y_sct = Dispatcher().select("start_row", sct_range_as_row_columns, fallback=0)
    return abs(x - x_sct) + abs(y - y_sct)
Example #3
0
def find_chart_anchor(chart):
    raw_row_columns = Dispatcher().select(
        "position.overlayPosition.anchorCell", chart)
    return {
        "start_row":
        Dispatcher().select("rowIndex", raw_row_columns, fallback=0),
        "start_column":
        Dispatcher().select("columnIndex", raw_row_columns, fallback=0),
    }
Example #4
0
def infer_chart_type(chart):
    chart_types = [
        "basicChart",
        "pieChart",
        "bubbleChart",
        "candlestickChart",
        "orgChart",
        "histogramChart",
        "waterfallChart",
        "treemapChart",
    ]
    for chart_type in chart_types:
        if Dispatcher().select(f"spec.{chart_type}", chart) is not None:
            return chart_type
Example #5
0
def has_equal_data_validation(state, incorrect_msg=None):
    child = check_range(state, field="dataValidations", field_msg="data validation")

    student_data_validation = child.student_data
    solution_data_validation = child.solution_data

    message = "In cell `{range}`, did you use the correct data validation?"

    # For now, we generally only support cells, not ranges. This means we always
    # have to look at the content at index 0, 0.
    condition_path = "0.0.condition"
    student_data_validation_condtion = Dispatcher().select(
        condition_path, student_data_validation
    )
    solution_data_validation_condtion = Dispatcher().select(
        condition_path, solution_data_validation
    )
    if student_data_validation_condtion != solution_data_validation_condtion:
        child.report(
            (incorrect_msg or message).format(**state.to_message_exposed_dict())
        )

    return state
Example #6
0
 def __init__(self,
              student_data,
              solution_data,
              sct_range,
              reporter,
              force_diagnose=False):
     self.student_data = student_data
     self.solution_data = solution_data
     self.sct_range = sct_range
     self.reporter = reporter
     self.messages = []
     self.creator = None
     self.dispatcher = Dispatcher()
     self.node_name = "root"
     self.force_diagnose = force_diagnose
Example #7
0
def has_equal_number_format(state, incorrect_msg=None):
    child = check_range(state,
                        field="numberFormats",
                        field_msg="number format")

    student_number_format = child.student_data
    solution_number_format = child.solution_data

    generated_message = None
    standard_message = "In cell `{range}`, did you use the correct number format?"

    # For now, we generally only support cells, not ranges. This means we always
    # have to look at the content at index 0, 0.
    type_path = "0.0.numberFormat.type"
    student_number_format_type = Dispatcher().select(type_path,
                                                     student_number_format)
    solution_number_format_type = Dispatcher().select(type_path,
                                                      solution_number_format)
    if student_number_format_type != solution_number_format_type:
        actual_type = number_format_types.get(student_number_format_type)
        expected_type = number_format_types.get(solution_number_format_type)
        if actual_type is None or expected_type is None:
            generated_message = standard_message
        else:
            generated_message = (
                standard_message +
                f" Expected {expected_type}, but got {actual_type}.")
    elif student_number_format != solution_number_format:
        generated_message = standard_message

    if generated_message is not None:
        child.report(
            (incorrect_msg
             or generated_message).format(**state.to_message_exposed_dict()))

    return state