Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
nnichols committed Jun 11, 2023
1 parent 72d20aa commit 1e9b875
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 109 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@ Below are examples of provided functionality for each namespace.
The library does provide access to other functions, but those primarily exist in support of those outlined here.

- [Calculations](doc/api/calculations.md)
- [Color](doc/api/color.md)
- [Precision](doc/api/precision.md)
- [Predicates](doc/api/predicates.md)
- [Units of Measure](doc/api/units.md)
- [Wrapping](doc/api/wrapping.md)

## Common Patterns

Brewtility follows several conventions and design patterns that result in artifacts available to library consumers.
These are not strictly required for use; however, they provide additional documentation and ease-of-use to those who adopt them.

- [Symbolic Keywords](doc/patterns/symbolic_keywords.md)

## Testing

[doo](https://github.com/bensu/doo), a Leiningen plugin used to run ClojureScript tests in many JS environments, is already in `project.clj`.
Expand Down
45 changes: 0 additions & 45 deletions doc/api/color.md

This file was deleted.

197 changes: 136 additions & 61 deletions doc/api/units.md
Original file line number Diff line number Diff line change
@@ -1,94 +1,169 @@
# Units of Measure

Beer has become an international interest/
Beer has become an international interest.
Additionally, brewing spans across the commercial and home environments.
As a result, the systems of measure and scales of measure can very greatly between brewers.
The BeerXML spec clearly delineates what units of measure are to be used to storing and transmitting data; however, they also allow users to pass `display` formats for values.
These are used to translate uniform, machine-friendly systems into more appropriate systems and scales based on geographic region and user case.

## Systems of Measure
The `brewtility.units` namespace contains functions to convert between different systems and units of measure across several different types of measurement.
Additionally, this namespace may be used to render common display formats.

Brewtility supports four systems of measure:
The names of these systems and units are frequently used in code, and shorthand symbolic references to these names may be found in `brewtility.units.options`

- [The British Imperial System](https://en.wikipedia.org/wiki/Imperial_units)
- [The Metric System](https://en.wikipedia.org/wiki/Metric_system)
- [The International System](https://en.wikipedia.org/wiki/International_System_of_Units)
- [The US Customary Scale](https://en.wikipedia.org/wiki/United_States_customary_units)
## Basic Use

## Volume Conversion

Given a `volume` in `source-measurement`, convert it to the `target-measurement`.
Supported measurements are:

- Teaspoon
- Tablespoon
- Imperial Fluid Ounce
- American Fluid Ounce
- Cup
- Imperial Pint
- American Pint
- Imperial Quart
- American Quart
- Imperial Gallon
- American Gallon
- Litre (Or Liter, depending on regional convention)
- Millilitre (Or Milliliter, depending on regional convention)
The majority of the functionality belongs to the functions `convert` and `display`.
This provides a consistent interface to every system of measure, unit type, and more.

```clj
(:require [brewtility.units :refer :all])
(:require [brewtility.units :as units]
[brewtility.units.options :as options]
[brewtility.units.volume :as volume])

(convert-volume 1.0 :liter :litre)
;; You can use the keys in `brewtility.units.options` as arguments.
;; This guarantees you don't have typos in code, and can link to helpful documentation
(units/convert units/volume 1.0 options/liter options/litre)
;; => 1.0

(convert-volume 20 :teaspoon :liter)
;; Or, if you prefer, bare keywords are accepted too
(units/convert units/volume 20 :teaspoon :liter)
;; => 0.099

(convert-volume 9.99209 :imperial-pint :american-pint)
;; If you only plan on dealing with volumes,
;; then you can import the `brewtility.units.volume` namespace
(volume/convert 9.99209 :imperial-pint :american-pint)
;; => 12.0

;; You can also render display values
(units/display :volume 1.5 :liter)
;; => \"1.5 l\"

;; The keys in `brewtility.units.options` are also acceptable
(units/display options/volume 1.5 options/liter)
;; => \"1.5 l\"

;; You may supply additional options, such as the default precision for rounding
;; and the type of suffix to use
(units/display options/volume 1.45 options/liter {options/precision 1})
;; => \"1.5 l\"

(units/display options/volume 1.45 options/liter {options/suffix options/full})
;; => \"1.45 liter\"

;; Like `convert`, you can also call the measurement-type's functionality directly
(volume/display 1.45 options/liter {options/precision 1})
;; => \"1.5 l\"

;; And, of course, the symbolic keywords are ultimately plain keywords.
(volume/display 1.45 :liter {:suffix :full :precision 1})
;; => \"1.5 liter\"
```

## Weight Conversion
## Supported Systems

Given a `weight` in `source-measurement`, convert it to the `target-measurement`.
Supported measurements are:
Brewtility supports four systems of measure:

- Ounce
- Pound
- Milligram
- Gram
- Kilogram
- [The British Imperial System](https://en.wikipedia.org/wiki/Imperial_units)
- [The Metric System](https://en.wikipedia.org/wiki/Metric_system)
- [The International System](https://en.wikipedia.org/wiki/International_System_of_Units)
- [The US Customary Scale](https://en.wikipedia.org/wiki/United_States_customary_units)

```clj
(:require [brewtility.units :refer :all])
These are the most commonly seen systems in brewing.
There are measurement functions for the most common types of measurements within these systems:

(convert-weight 1.0 :kilogram :kilogram)
;; => 1.0
- [Color](##color)
- [Pressure](##pressure)
- [Specific Gravity](##specific-gravity)
- [Temperature](##temperature)
- [Time](##time)
- [Volume](##volume)
- [Weight](##weight)

(convert-weight 15.0 :pound :ounce)
;; => 240.0
### Color

(convert-weight 1205.5 :milligram :pound)
;; => 0.003
```
Currently, brewtility supports the following types of color:

## Temperature Conversion
- [SRM](https://en.wikipedia.org/wiki/Standard_Reference_Method)
- [EBC](https://en.wikipedia.org/wiki/European_Brewery_Convention)
- [Lovibond](https://en.wikipedia.org/wiki/Beer_measurement#Colour)
- [RGBa](https://en.wikipedia.org/wiki/RGBA_color_model)

Given a `temperature` in `source-measurement`, convert it to the `target-measurement`.
Supported measurements are:
The `RGBa` system is special, as it can only be used as an argument for the result of a unit conversion.
Unfortunately, there is not a great deterministic way to cast the values back to the other systems.
brewtility will thrown an exception in this case and explain the problem.

- Celsius (Or Centigrade, depending on regional convention. Or C, for convenience)
- Kelvin (Or K, for convenience)
- Fahrenheit (Or F, for convenience)
### Pressure

```clj
(:require [brewtility.units :refer :all])
Currently, brewtility supports the following types of pressure:

(convert-temperature 32.0 :fahrenheit :fahrenheit)
;; => 32.0
- [pascal](https://en.wikipedia.org/wiki/Pascal_(unit)#Multiples_and_submultiples)
- [kilopascal](https://en.wikipedia.org/wiki/Pascal_(unit)#Multiples_and_submultiples)
- [bar](https://en.wikipedia.org/wiki/Bar_(unit))
- [atmosphere](https://en.wikipedia.org/wiki/Atmosphere_(unit))
- [torr](https://en.wikipedia.org/wiki/Torr)
- [psi](<https://en.wikipedia.org/wiki/Pound-force_per_square_inch>

(convert-temperature 0.0 :c :f)
;; => 32.0
### Specific Gravity

(convert-temperature 2016.3 :kelvin :c)
;; => 1743.15
```
Currently, brewtility supports the following types of specific gravity:

- [specific-gravity](https://en.wikipedia.org/wiki/Specific_gravity)

While there is currently only one system, the same namespace and functionality exists as the other measurement types.
This allows for progressive evolution, and provides a consistent interface to every measurement type encoded in the BeerXML specification.

### Temperature

Currently, brewtility supports the following types of temperature measurements:

- [clesius](https://en.wikipedia.org/wiki/Celsius)
- [fahrenheit](https://en.wikipedia.org/wiki/Fahrenheit)
- [kelvin](https://en.wikipedia.org/wiki/Kelvin_(unit))

Given the prevalence of shorthand names in temperature measurements, brewtility also accepts `c`, `k`, and `f`.

### Time

Currently, brewtility supports the following types of time measurements:

- [microsecond](https://en.wikipedia.org/wiki/Microsecond)
- [nanosecond](https://en.wikipedia.org/wiki/Nanosecond)
- [millisecond](https://en.wikipedia.org/wiki/Millisecond)
- [second](https://en.wikipedia.org/wiki/Second)
- [minute](https://en.wikipedia.org/wiki/Minute)
- [hour](https://en.wikipedia.org/wiki/Hour)
- [day](https://en.wikipedia.org/wiki/Day)
- [week](https://en.wikipedia.org/wiki/Week)

### Volume

Currently, brewtility supports the following types of volume:

- [american-fluid-ounce](https://en.wikipedia.org/wiki/Fluid_ounce)
- [american-gallon](https://en.wikipedia.org/wiki/Gallon)
- [american-pint](https://en.wikipedia.org/wiki/Pint)
- [american-quart](https://en.wikipedia.org/wiki/Quart)
- [cup](https://en.wikipedia.org/wiki/Cup_(unit))
- [imperial-fluid-ounce](https://en.wikipedia.org/wiki/Fluid_ounce)
- [imperial-gallon](https://en.wikipedia.org/wiki/Gallon)
- [imperial-pint](https://en.wikipedia.org/wiki/Pint)
- [imperial-quart](https://en.wikipedia.org/wiki/Quart)
- [liter](https://en.wikipedia.org/wiki/Litre)
- [litre](https://en.wikipedia.org/wiki/Litre)
- [milliliter](https://en.wikipedia.org/wiki/Millilitre)
- [millilitre](https://en.wikipedia.org/wiki/Millilitre)
- [tablespoon](https://en.wikipedia.org/wiki/Tablespoon)
- [teaspoon](https://en.wikipedia.org/wiki/Teaspoon))

Given the prevalence of the French spellings in English recipes, both `:litre` and `:liter` can be passed as options.

### Weight

Currently, brewtility supports the following types of weight:

- [gram](https://en.wikipedia.org/wiki/Gram)
- [milligram](https://en.wikipedia.org/wiki/Milligram)
- [kilogram](https://en.wikipedia.org/wiki/Kilogram)
- [ounce](https://en.wikipedia.org/wiki/Ounce)
- [pound](https://en.wikipedia.org/wiki/Pound_(mass))
7 changes: 5 additions & 2 deletions doc/cljdoc.edn
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
["Changelog" {:file "CHANGELOG.md"}]
["Community" {}
["Contributing" {:file "CONTRIBUTING.md"}]
["Code of Conduct" {:file "CODE_OF_CONDUCT.md"}]]
["Code of Conduct" {:file "CODE_OF_CONDUCT.md"}]
["Security Policy" {:file "SECURITY.md"}]]
["Functionality" {}
["Calculations" {:file "doc/api/calculations.md"}]
["Color" {:file "doc/api/color.md"}]
["Precision" {:file "doc/api/precision.md"}]
["Predicates" {:file "doc/api/predicates.md"}]
["Units of Measure" {:file "doc/api/units.md"}]
["Wrapping" {:file "doc/api/wrapping.md"}]]]}
["Wrapping" {:file "doc/api/wrapping.md"}]]
["Adopted Patterns" {}
["Symbolic Keywords" {:file "doc/patterns/symbolic_keywords.md"}]]]}
51 changes: 51 additions & 0 deletions doc/patterns/symbolic_keywords.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Symbolic Keywords

In many clojure libraries, the behavior of complex functions may be controlled by a map.
For example:

```clojure
(:require [brewtility.units :as units])
(units/display :volume 1.5 :liter) ;; => "1.5 l"
(units/display :volume 1.5 :liter {:suffix :full}) ;; => "1.5 liter"
```

This allows us to easily extend the definition of a single function to fulfil multiple complex needs; however, option maps come with considerable drawbacks.
When a map is keyed with keywords, it is easy to introduce subtle, hard-to-detect errors.
Since most of these functions select default values for keys not present, typos can lead to meaningful differences in behavior.
For example:

```clojure
(:require [brewtility.units :as units])
(units/display :volume 1.5 :liter) ;; => "1.5 l"

;; Not the missing "f" in the key :sufix
(units/display :volume 1.5 :liter {:sufix :full}) ;; => "1.5 l"
```

Because keywords aren't picked up by the auto-complete features of most editors, they're vulnerable to all classes of transpositional errors.
Further, the options themselves are unable to carry metadata and documentation with them, making them little more than magic values.

For this reason, it is helpful for libraries to include symbols which point to the "magic" keywords used in option maps.
This has several benefits:

- Misspelled or incorrect option keys are compile-time errors, instead of runtime bugs
- Symbols can carry metadata like documentation, deprecation notices, and point to alternative options
- Context-aware editors can auto-complete options

Here's can example:

```clojure
(:require [brewtility.units :as units]
[brewtility.units.options :as options])

(units/display options/volume 1.5 options/liter) ;; => "1.5 l"
(units/display options/volume 1.5 options/liter {options/suffix options/full}) ;; => "1.5 liter"
```

Most option maps in `brewtility` support symbolic keywords.
These keywords are available in the namespaces ending in `.options`.
These files live as close to the code relying on them as possible;
for example, the options for all unit conversion operations (e.g. `brewtility.units`, `brewtility.units.time`, `brewtility.units.color`, etc.) are available in `brewtility.units.options`.

Further, the option keywords are preferred for library development.
A single source of truth for the name of a common option, such as `precision`, limits the possibility of incorrectly retrieving the values used by that option.

0 comments on commit 1e9b875

Please sign in to comment.