<commit_before>defmodule WhiteBread.Runners.FeatureRunner do

  def run(feature, context, output_pid) do
    %{scenarios: scenarios, background_steps: background_steps} = feature
    results = scenarios
      |> run_all_scenarios_for_context(context, background_steps)
      |> flatten_any_result_lists
      |> output_results(feature, output_pid)

    %{
      successes: results |> Enum.filter(&is_success/1),
      failures:  results |> Enum.filter(&is_failure/1)
    }
  end

  defp run_all_scenarios_for_context(scenarios, context, background_steps) do
    starting_state = apply(context, :feature_state, [])
    scenarios
      |> Stream.map(&run_scenario(&1,context, background_steps, starting_state))
  end

  defp run_scenario(scenario,context, background_steps, starting_state) do
    result = run(scenario, context, background_steps, starting_state)
    {scenario, result}
  end

  defp flatten_any_result_lists(results) do
    flatten = fn
      ({scenario, results}) when is_list(results) ->
        results |> Enum.map(fn(result) -> {scenario, result} end)
      (single) ->
        [single]
    end
    results |> Stream.flat_map(flatten)
  end

  defp output_results(results, feature, output_pid) do
    send_results = fn({scenario, result}) ->
      send(output_pid, {:scenario_result, result, scenario, feature})
    end
    results
      |> Stream.each(send_results)
      |> Stream.run

    results
  end

  defp is_success({_scenario, {success, _}}) do
    success == :ok
  end

  defp is_failure({_scenario, {success, _}}) do
    success == :failed
  end

  defp run(scenario, context, background_steps, starting_state) do
    scenario
      |> WhiteBread.Runners.run(context, background_steps, starting_state)<commit_msg>rename bool funcs in feature runner<commit_after>defmodule WhiteBread.Runners.FeatureRunner do

  def run(feature, context, output_pid) do
    %{scenarios: scenarios, background_steps: background_steps} = feature
    results = scenarios
      |> run_all_scenarios_for_context(context, background_steps)
      |> flatten_any_result_lists
      |> output_results(feature, output_pid)

    %{
      successes: results |> Enum.filter(&success?/1),
      failures:  results |> Enum.filter(&failure?/1)
    }
  end

  defp run_all_scenarios_for_context(scenarios, context, background_steps) do
    starting_state = apply(context, :feature_state, [])
    scenarios
      |> Stream.map(&run_scenario(&1,context, background_steps, starting_state))
  end

  defp run_scenario(scenario,context, background_steps, starting_state) do
    result = run(scenario, context, background_steps, starting_state)
    {scenario, result}
  end

  defp flatten_any_result_lists(results) do
    flatten = fn
      ({scenario, results}) when is_list(results) ->
        results |> Enum.map(fn(result) -> {scenario, result} end)
      (single) ->
        [single]
    end
    results |> Stream.flat_map(flatten)
  end

  defp output_results(results, feature, output_pid) do
    send_results = fn({scenario, result}) ->
      send(output_pid, {:scenario_result, result, scenario, feature})
    end
    results
      |> Stream.each(send_results)
      |> Stream.run

    results
  end

  defp success?({_scenario, {success, _}}), do: success == :ok
  defp failure?({_scenario, {success, _}}), do: success == :failed

  defp run(scenario, context, background_steps, starting_state) do
    scenario
      |> WhiteBread.Runners.run(context, background_steps, starting_state)
{'fraction_non_alphanumeric': 0.10903873744619799, 'fraction_numerical': 0.001721664275466284, 'mean_word_length': 3.8892005610098175, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 33, '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': '4614300', 'n_tokens_mistral': 1126, 'n_tokens_neox': 1098, 'n_words': 234}