Skip to content

Instantly share code, notes, and snippets.

@rekyuu
Created September 18, 2018 15:31
Show Gist options
  • Save rekyuu/7a35756f05a60e1223abf0f4896b9da3 to your computer and use it in GitHub Desktop.
Save rekyuu/7a35756f05a60e1223abf0f4896b9da3 to your computer and use it in GitHub Desktop.
Elixir ErlangC
defmodule ErlangC do
def factorial_of(0), do: 1
def factorial_of(n) when n > 0, do: n * factorial_of(n - 1)
def traffic_intensity(calls, reporting_period, average_handle_time) do
calls_per_hour = (60 / reporting_period) * calls
(calls_per_hour * (average_handle_time / 60)) / 60
end
def probability_call_waits(traffic_intensity, agents) do
numerator = (:math.pow(traffic_intensity, agents) / factorial_of(agents)) * (agents / (agents - traffic_intensity))
sigma = Enum.map(0..(agents - 1), fn(i) ->
:math.pow(traffic_intensity, i) / factorial_of(i)
end) |> Enum.sum
denominator = sigma + numerator
numerator / denominator
end
def service_level(traffic_intensity, agents, target_answer_time, average_handle_time) do
1 - (probability_call_waits(traffic_intensity, agents) * :math.exp(-((agents - traffic_intensity) * (target_answer_time / average_handle_time))))
end
def average_speed_of_answer(average_handle_time, agents, traffic_intensity) do
(probability_call_waits(traffic_intensity, agents) * average_handle_time) / (agents - traffic_intensity)
end
def raw_agents_needed(traffic_intensity, target_answer_time, average_handle_time, required_service_level) do
agents = Kernel.trunc(traffic_intensity + 1)
Enum.reduce_while(1..(255 - agents), agents, fn (i, acc) ->
service_level = ErlangC.service_level(traffic_intensity, acc, target_answer_time, average_handle_time)
if service_level < required_service_level do
{:cont, acc + i}
else
{:halt, acc}
end
end) |> Kernel.trunc
end
def agents_needed(traffic_intensity, target_answer_time, average_handle_time, required_service_level, shrinkage) do
Kernel.trunc(raw_agents_needed(traffic_intensity, target_answer_time, average_handle_time, required_service_level) / (1 - shrinkage))
end
end
defmodule Factorial do
def of(0), do: 1
def of(n) when n > 0, do: n * of(n - 1)
end
calls = 100
reporting_period = 30.0 # in minutes
average_handle_time = 180.0 # in seconds
required_service_level = 0.80
target_answer_time = 20.0 # in seconds
shrinkage = 0.30
traffic_intensity = ErlangC.traffic_intensity(calls, reporting_period, average_handle_time)
raw_agents_needed = ErlangC.raw_agents_needed(traffic_intensity, target_answer_time, average_handle_time, required_service_level)
agents_needed = ErlangC.agents_needed(traffic_intensity, target_answer_time, average_handle_time, required_service_level, shrinkage)
service_level = Float.round(ErlangC.service_level(traffic_intensity, raw_agents_needed, target_answer_time, average_handle_time) * 100, 2)
call_wait_probability = Float.round(ErlangC.probability_call_waits(traffic_intensity, raw_agents_needed) * 100, 2)
asa = Float.round(ErlangC.average_speed_of_answer(average_handle_time, raw_agents_needed, traffic_intensity), 2)
IO.puts "Raw agents required: #{raw_agents_needed}"
IO.puts "Agents required (with shrinkage): #{agents_needed}"
IO.puts "Service level: #{service_level}%"
IO.puts "Probability a call has to wait: #{call_wait_probability}%"
IO.puts "Average Speed of Answer: #{asa}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment