General
What is Calcarta?
Calcarta is an interactive verifiable encyclopaedia that aims to be the definitive source of independently verifiable methods, calculations and generated documents. Calcarta is built on the idea of community input and we encourage everyone to contribute new calculations or to existing ones.
To use Calcarta you do not need to know how to read or write computer code. Our aim is to make it possible to verify the calculations you're using should you wish to do so (if not, that's ok too!).
Calcarta consists of three main 'repository' types; Calculations, Code Resources and File Collections. The vast majority of people will only use the Calculation repositories. These provide the ability interact with calculations via a forms system. Code Resource repositories aim to provide standard frameworks for use by the various Calculation repositories. Finally, File Collection repositories allow for raw data such documents and images to be used by the Calculation repositories.
All code in Calcarta is written using the open source functional language F#. We believe this language provides an optimal mix of power, flexibility and readability by non-programmers. Officially supported by Microsoft with a strong community there are many learning resources available on the internet, as a start we'd recommend the following sites:
- https://fsharpforfunandprofit.com/learning-fsharp/
- https://docs.microsoft.com/en-us/dotnet/fsharp/
- https://fsharp.org/
Getting started
It's probably easiest to begin with a simple example. In this case we'll implement the Body Mass Index (or BMI for short) calculation that is used in healthcare to estimate how a persons weight compares with the standard population (i.e. underweight, normal, overweight, obese). It's a pretty simple calculation that takes a persons weight in kilograms and then divides it by their height (in metres) squared.
The first step is to create a new calculation repository (to do this you'll need to have signed up to a free account). The 'Create' link is up in the top of the page in the navigation bar. Make sure to choose the Calculation repository type when creating it.
The next step is to navigate to the repository details page and go to the 'versions' tab. Once there, create a new 'Calculation Code' version (there'll also be the option to create a unit test version but don't worry about that for now) and click on it to edit.
Now it's time to enter some code. When you create a new version it will generate a default template for you to edit. Here's what it might first look like...
module Calcarta.Calculation.Bmi.Code
open Calcarta.CodeResource.Standard
[<Name("", AppliesTo=Argument.Input)>]
[<Description("", AppliesTo=Argument.Input)>]
[<Unit("", AppliesTo=Argument.Input)>]
[<Name("", AppliesTo=Argument.Output)>]
[<Description("", AppliesTo=Argument.Output)>]
[<Unit("", AppliesTo=Argument.Output)>]
let bmi input = ...
Ok, that's a bit complicated so let's cut it down to the essentials.
module Calcarta.Calculation.Bmi.Code
open Calcarta.CodeResource.Standard
let bmi input = ...
Breaking it down, we start off by declaring the name of the calculation Calcarta.Calculation.Bmi.Code, there's no choice about this and needs to remain as is. The next essential is where it imports the Calcarta.CodeResource.Standard Code Resource, technically you don't absolutely need this but it provides a lot of basic functionality. Finally there's the actual calculation itself, this can be anything you like, the only import thing is that the calculation comes last in your code and has only one input argument.
Whilst the calculation input can only have one argument, this argument can be composed of multiple fields. In this case we need to know the patients height and weight in decimal figures. In order to do this we can create a 'type' (more specifically an F# Record) to structure this information. We should also make the 'input' argument more relevant to the calculation. In this case we'll change it from 'input' to 'patient'.
module Calcarta.Calculation.Bmi.Code
open Calcarta.CodeResource.Standard
type Person = {
Height : decimal
Weight : decimal
}
let bmi patient = ...
As you can see, we've specified a Patient as having both a decimal height and a decimal weight. The next thing to do is implement the BMI calculation itself.
module Calcarta.Calculation.Bmi.Code
open Calcarta.CodeResource.Standard
type Person = {
Height : decimal
Weight : decimal
}
let bmi patient = patient.Weight / (patient.Height * patient.Height)
And that's it! Calcarta will automatically figure out that it needs to ask for Height and Weight and will generate an output. Having said that, we probably want to make the output more explanatory to the end-user hence we start thinking about attributes.
Attributes don't affect the calculation but they do allow the author to configure how it's displayed. In this case we want the output to be named 'Body Mass Index (BMI)'. We also want to put an instruction on the Height measurement to ensure it's taken correctly and specify the measurement units of Height and Weight.
module Calcarta.Calculation.Bmi.Code
open Calcarta.CodeResource.Standard
type Person = {
[<Description("Ensure the person is standing fully upright against a wall when taking the measurement")>]
[<Unit("Metre")>]
Height : decimal
[<Unit("Kilogram")>]
Weight : decimal
}
[<Name("Body Mass Index (BMI)", AppliesTo=Argument.Output)>]
[<Unit("kg/m²", AppliesTo=Argument.Output)>]
let bmi patient = patient.Weight / (patient.Height * patient.Height)
There're a few things going on here. Firstly, attributes can be added to any of the values we are requesting or outputing (in this case we've added Name, Unit and Description attributes). Secondly, if we add attributes to our main calculation (i.e. let bmi patient = ...) then we need to specify whether it applies to the argument input or output. When we specified the Description and Unit attributes on the person's height and weight, it's implicit these apply to input arguments.
This works fine if we're in a country that uses Metric measurements however it'd be useful to be able to enter other units. For example, we'd like to avoid the situation where we've got one calculation for metric units and another for imperial units. The solution is the Units Code Resource...
module Calcarta.Calculation.Bmi.Code
open Calcarta.CodeResource.Standard
open Calcarta.CodeResource.Units.QuantitiesOfMechanics.Mass
open Calcarta.CodeResource.Units.SpaceAndTime.Length
type Person = {
[<Description("Ensure the person is standing fully upright against a wall when taking the measurement")>]
[<Unit(Metre)>]
Height : decimal
[<Unit(Kilogram)>]
Weight : decimal
}
[<Name("Body Mass Index (BMI)", AppliesTo=Argument.Output)>]
[<Unit("kg/m²", AppliesTo=Argument.Output)>]
let bmi patient = patient.Weight / (patient.Height * patient.Height)
Here we've imported two new repositories Calcarta.CodeResource.Units.QuantitiesOfMechanics.Mass and Calcarta.CodeResource.Units.SpaceAndTime.Length (well technically just one repository as they both live in the Calcarta.CodeResource.Units repository). We've also removed the speech marks around Metre and Kilogram as they now refer to values in the Units Code Resource. By specifying Metre and Kilometre we've told Calcarta they're the expected units of those values. However, when entering these values on the form, Calcarta will now display a drop-down box that allows for other units to be entered and automatically converts them to whatever the calculation requires. If you want to know what other conversions are possible, have a look at the Units Code Resource itself.