acquisitionuniverse for Elixir

Elixir functions for people who work through acquisition target lists. Rank companies, validate a thesis brief, print it as text and count which of the 15 common signals are actually visible. Plain maps in, plain maps out, no dependencies.

{:acquisitionuniverse, "~> 1.0"}

Rank

companies = [
  %{id: "A", mandate_fit: 90, outreach_suitability: 80, transition_context: 50},
  %{id: "B", mandate_fit: 96, outreach_suitability: 90, transition_context: 70, group_owned: true}
]

AcquisitionUniverse.rank(companies) |> Enum.map(&{&1.id, &1.composite})
# [{"A", 84.0}, {"B", 74.2}]

B is the stronger fit. It is owned by a group, so it carries no outreach points and A comes first. Provide your own weights as a map with :mandate_fit, :outreach_suitability and :transition_context.

Brief

brief = %{
  name: "Precision machining, Carolinas",
  vertical: "Precision machining",
  regions: ["North Carolina", "South Carolina"],
  employees_min: 10,
  employees_max: 90,
  exclusions: ["group-owned"]
}

[] = AcquisitionUniverse.validate_brief(brief)
IO.puts(AcquisitionUniverse.brief_text(brief))

Coverage

[s0, _, s2 | _] = AcquisitionUniverse.signals()
AcquisitionUniverse.signal_coverage(%{s0 => "family associated", s2 => nil})
# %{visible: 1, checked: 2, ratio: 0.5}

Functions

Function Result
signals/0 list of 15 names
default_weights/0 0.7, 0.2, 0.1
composite/2 float, 0 to 100
rank/2 maps with :composite, best first
signal_coverage/1 map with visible, checked, ratio
validate_brief/1 list of problems
brief_text/1 string
pilot_url/0 pilot request page

LiveView idea

A LiveView with a form for the weights and a table for rank/2 lets a partner drag the balance between fit and suitability and watch the list reorder. The data is just a list of maps, so Phoenix.LiveView.stream/3 fits well.

Process a CSV

rows =
  "screen.csv"
  |> File.stream!()
  |> Stream.drop(1)
  |> Stream.map(&String.split(String.trim(&1), ","))
  |> Enum.map(fn [id, fit, out, trans, owned] ->
    %{id: id, mandate_fit: String.to_float(fit), outreach_suitability: String.to_float(out),
      transition_context: String.to_float(trans), group_owned: owned == "yes"}
  end)

AcquisitionUniverse.rank(rows) |> Enum.take(10)

Add-on buyers can compare notes in the portfolio company BD guide. The same team publishes cookieless audience database material for curation platforms and a skill normalization reference for resume data.

Questions

Does it call a server? No.

Elixir version? 1.14 or later.

License? MIT. info@alpha-quantum.com