<commit_before>local function gui_header_create(parent)
  local header = parent.add({ type = "flow", name = "header", direction = "horizontal" })
  header.add { type = "button", name = "usage_detector_start", caption = "Start" }
  header.add { type = "button", name = "usage_detector_stop", caption = "Stop" }

  header.add { type = "label", name = "item_label", caption = "Item" }
  local item = header.add { type = "choose-elem-button", name = "item", elem_type = "item" }

  header.add { type = "label", name = "fluid_label", caption = "or Fluid" }
  local fluid = header.add { type = "choose-elem-button", name = "fluid", elem_type = "fluid" }
  -- TODO: If a job exists, load it
end

local function create(player)
  local frame = player.gui.center.add({ type = "frame", name = "usage_detector_center", direction = "vertical" })

  local section = frame.add { type = "flow", name = "section0", direction = "vertical" }
  gui_header_create(section)
  section.add { type = "label", name = "job_status", caption = "Not started." }

  local table_container = section.add { type = "flow", name = "table_container", direction = "horizontal" }
	table_container.style.minimal_width = 700
	table_container.style.minimal_height = 600
end

local function recreate_table_with_results(section, results)
  local table_container = section["table_container"]
  local table = table_container.add { type = "table", name = "table", column_count = 7 }
  table.add { type = "label", name = "header_name", caption = "Recipe Name" }
  table.add { type = "label", name = "header_amount", caption = "Amount" }
  table.add { type = "label", name = "header_count", caption = "Times produced" }
  table.add { type = "label", name = "header_sum", caption = "Total used" }
  table.add { type = "label", name = "header_machine_count", caption = "Machine count" }
  table.add { type = "label", name = "header_per_second", caption = "Used per second" }
  table.add { type = "label", name = "header_percent", caption = "Used %" }

  local sum = 0
  for _, result in pairs(results) do
    sum = sum + result.amount * result.count
  end

  for recipe_name, result in pairs(results) do
    local name_prefix = "result_" .. recipe_name .. "_"
    table.add { type = "label", name = name_prefix .. "name", caption = recipe_name }
    table.add { type = "label", name = name_prefix .. "amount", caption = result.amount }
    table.add { type = "label", name = name_prefix .. "count", caption = result.count }
    table.add { type = "label", name = name_prefix .. "sum", caption = result.amount * result.count }
    table.add { type = "label", name = name_prefix .. "machine_count", caption = result.machine_count }
    table.add { type = "label", name = name_prefix .. "per_second", caption = "" }
    table.add { type = "label", name = name_prefix .. "percent", caption = "" }
  end
end

local function update_job(player, section_name, job_data)
  local job_gui = player.gui.center.usage_detector_center[section_name]
  if job_gui.table_container["table"] then
    job_gui.table_container.table.destroy()
  end
  local stopped = job_data.stopped_at > job_data.started_at
  local stopped_at = stopped and job_data.stopped_at or game.tick
  local running_label = string.format("Running for %d ticks.", stopped_at - job_data.started_at)
  job_gui.job_status.caption = game.tick > job_data.started_at and running_label or "Not started."

  recreate_table_with_results(job_gui, job_data.results)
end

local function click(player, event, usage_detector)
  if event.element.name == "usage_detector_start" then
    local section_name = event.element.parent.parent.name
    usage_detector.start(player, { type = "item", name = "iron-plate" }, section_name)
  end
  if event.element.name == "usage_detector_stop" then
    local section_name = event.element.parent.parent.name
    usage_detector.stop(player, section_name)<commit_msg>Usage Detector: Add used_per_second and used_percent calculations<commit_after>local function gui_header_create(parent)
  local header = parent.add({ type = "flow", name = "header", direction = "horizontal" })
  header.add { type = "button", name = "usage_detector_start", caption = "Start" }
  header.add { type = "button", name = "usage_detector_stop", caption = "Stop" }

  header.add { type = "label", name = "item_label", caption = "Item" }
  local item = header.add { type = "choose-elem-button", name = "item", elem_type = "item" }

  header.add { type = "label", name = "fluid_label", caption = "or Fluid" }
  local fluid = header.add { type = "choose-elem-button", name = "fluid", elem_type = "fluid" }
  -- TODO: If a job exists, load it
end

local function create(player)
  local frame = player.gui.center.add({ type = "frame", name = "usage_detector_center", direction = "vertical" })

  local section = frame.add { type = "flow", name = "section0", direction = "vertical" }
  gui_header_create(section)
  section.add { type = "label", name = "job_status", caption = "Not started." }

  local table_container = section.add { type = "flow", name = "table_container", direction = "horizontal" }
	table_container.style.minimal_width = 700
	table_container.style.minimal_height = 600
end

function round_to_closest(number, precision)
  return math.floor(number / precision + 0.5) * precision
end

local function recreate_table_with_results(section, results, running_time)
  local table_container = section["table_container"]
  local table = table_container.add { type = "table", name = "table", column_count = 7 }
  table.add { type = "label", name = "header_name", caption = "Recipe Name" }
  table.add { type = "label", name = "header_amount", caption = "Amount" }
  table.add { type = "label", name = "header_count", caption = "Times produced" }
  table.add { type = "label", name = "header_sum", caption = "Total used" }
  table.add { type = "label", name = "header_machine_count", caption = "Machines" }
  table.add { type = "label", name = "header_per_second", caption = "Used per second" }
  table.add { type = "label", name = "header_percent", caption = "Used %" }

  local all_sum = 0
  for _, result in pairs(results) do
    all_sum = all_sum + result.amount * result.count
  end

  local running_seconds = running_time / 60
  for recipe_name, result in pairs(results) do
    local name_prefix = "result_" .. recipe_name .. "_"
    local recipe_sum = result.amount * result.count
    table.add { type = "label", name = name_prefix .. "name", caption = recipe_name }
    table.add { type = "label", name = name_prefix .. "amount", caption = result.amount }
    table.add { type = "label", name = name_prefix .. "count", caption = result.count }
    table.add { type = "label", name = name_prefix .. "sum", caption = recipe_sum }
    table.add { type = "label", name = name_prefix .. "machine_count", caption = result.machine_count }
    local used_per_second = recipe_sum / running_seconds
    table.add { type = "label", name = name_prefix .. "per_second", caption = round_to_closest(used_per_second, 0.01) }
    local used_percent = recipe_sum / all_sum * 100
    table.add { type = "label", name = name_prefix .. "percent", caption = round_to_closest(used_percent, 0.01) }
  end
end

local function update_job(player, section_name, job_data)
  local job_gui = player.gui.center.usage_detector_center[section_name]
  if job_gui.table_container["table"] then
    job_gui.table_container.table.destroy()
  end
  local stopped = job_data.stopped_at > job_data.started_at
  local stopped_at = stopped and job_data.stopped_at or game.tick
  local running_time = stopped_at - job_data.started_at
  local running_label = string.format("Running for %d ticks.", running_time)
  job_gui.job_status.caption = game.tick > job_data.started_at and running_label or "Not started."

  recreate_table_with_results(job_gui, job_data.results, running_time)
end

local function click(player, event, usage_detector)
  if event.element.name == "usage_detector_start" then
    local section_name = event.element.parent.parent.name
    usage_detector.start(player, { type = "item", name = "iron-plate" }, section_name)
  end
  if event.element.name == "usage_detector_stop" then
    local section_name = event.element.parent.parent.name
    usage_detector.stop(player, section_name)
{'fraction_non_alphanumeric': 0.1326073805202662, 'fraction_numerical': 0.003750756200846945, 'mean_word_length': 4.228336495888678, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, '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': '914043', 'n_tokens_mistral': 2677, 'n_tokens_neox': 2566, 'n_words': 704}