# Cassowary

[![Luacheck](https://img.shields.io/github/workflow/status/sile-typesetter/cassowary.lua/Luacheck?label=Luacheck&logo=Lua)](https://github.com/sile-typesetter/cassowary.lua/actions?workflow=Luacheck)
[![Busted](https://img.shields.io/github/workflow/status/sile-typesetter/cassowary.lua/Busted?label=Busted&logo=Lua)](https://github.com/sile-typesetter/cassowary.lua/actions?workflow=Busted)
[![Coverage Status](https://img.shields.io/coveralls/github/sile-typesetter/cassowary.lua?label=Coveralls&logo=Coveralls)](https://coveralls.io/github/sile-typesetter/cassowary.lua?branch=master)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/sile-typesetter/cassowary.lua?label=Tag&logo=GitHub)](https://github.com/sile-typesetter/cassowary.lua/releases)
[![Luarocks](https://img.shields.io/luarocks/v/simoncozens/cassowary?label=Luarocks&logo=Lua)](https://luarocks.org/modules/simoncozens/cassowary)

This is a Lua port of the [cassowary](http://constraints.cs.washington.edu/cassowary/) constraint solving toolkit.
It allows you to use Lua to solve algebraic equations and inequalities and find the values of unknown variables which satisfy those inequalities.

This port is a fairly dumb, bug-for-bug translation of the [Javascript version of cassowary](https://github.com/slightlyoff/cassowary.js).
From that project's description:

> Cassowary and other hierarchial constraint toolkits add a unique mechanism for deciding between sets of rules that might conflict in determining which of a set of possible solutions are "better".
> By allowing constraint authors to specify weights for the constraints, the toolkit can decide in terms of stronger constraints over weaker ones, allowing for more optimal solutions.
> These sorts of situations arise all the time in UI programming; e.g.: "I'd like this to be it's natural width, but only if that's smaller than 600px, and never let it get smaller than 200px".
> Constraint solvers offer a way out of the primordial mess of nasty conditionals and brittle invalidations.

## Getting started

Cassowary.lua is distributed through [LuaRocks](https://luarocks.org/modules/simoncozens/cassowary).
Once installed:

```lua
cassowary = require("cassowary")

-- Create a new solver object
local solver = cassowary.SimplexSolver();

-- Create lua variables to represent x and y
local x = cassowary.Variable({ name = 'x' });
local y = cassowary.Variable({ name = 'y' });

-- Let's encode some expressions:

--    x < y
solver:addConstraint(cassowary.Inequality(x, "<=", y))

--    y = x + 3
solver:addConstraint(cassowary.Equation(y, cassowary.plus(x, 3)))

--    either x = 10 or y = 10
solver:addConstraint(cassowary.Equation(x, 10, cassowary.Strength.weak))
solver:addConstraint(cassowary.Equation(y, 10, cassowary.Strength.weak))

-- The solver automatically tries to resolve the current situation
-- whenever constraints are added, so all we need to do is look
-- at the values:

print("x = "..x.value)
print("y = "..y.value)
```

Depending on the phase of the moon, you will either see:

```
x=7
y=10
```

or

```
x=10
y=13
```

For further examples, see the test suite.

## Licence

This is a derived work of the Javascript port;
I've chosen to licensed it similarly under the Apache 2.0 license.

## Author

Simon Cozens, <simon@simon-cozens.org>
