73 lines
2.2 KiB
Markdown
73 lines
2.2 KiB
Markdown
|
# Cow Description Language (CDL)
|
||
|
In times of the pandemic, it's not easy to get real input data from your cows to
|
||
|
demonstrate the functionality of your front end. To be able to test some
|
||
|
features of the application, we would like to have scripts that
|
||
|
insert fake data points into our database, allowing us how our app
|
||
|
would behave in real time, without the need to hook up any collars.
|
||
|
These scripts would be tedius to write...
|
||
|
|
||
|
Unless, of course, you have a Domain Specific Language (DSL) for it!
|
||
|
Enter CDL. We can describe a cow in a turtle-style imperative language:
|
||
|
|
||
|
```Haskell
|
||
|
squareCow = do
|
||
|
move 10
|
||
|
turn 90
|
||
|
move 10
|
||
|
turn 90
|
||
|
move 10
|
||
|
turn 90
|
||
|
move 10
|
||
|
```
|
||
|
|
||
|
This DSL is shallowly embedded into Haskell, which means that we can
|
||
|
use all of Haskell's abstraction capabilities:
|
||
|
|
||
|
```Haskell
|
||
|
repeat 0 _ = return ()
|
||
|
repeat n thing = do
|
||
|
thing
|
||
|
repeat (n-1) thing
|
||
|
|
||
|
squareCow = repeat 4 $ do
|
||
|
move 10
|
||
|
turn 90
|
||
|
```
|
||
|
|
||
|
Given a sampling frequency, CDL can generate a Python script that
|
||
|
inserts data points into our database each "sample":
|
||
|
|
||
|
```Python
|
||
|
from server.fgs.model import *
|
||
|
from server.fgs import db
|
||
|
import datetime
|
||
|
db.session.add(DataPoint(longitude=0.0, latitude=0.0, datetime=datetime.now()))
|
||
|
db.session.commit()
|
||
|
sleep(0.1)
|
||
|
db.session.add(DataPoint(longitude=9.0000094e-7, latitude=0.0, datetime=datetime.now()))
|
||
|
db.session.commit()
|
||
|
sleep(0.1)
|
||
|
db.session.add(DataPoint(longitude=1.8000019e-6, latitude=0.0, datetime=datetime.now()))
|
||
|
db.session.commit()
|
||
|
sleep(0.1)
|
||
|
# ...
|
||
|
```
|
||
|
|
||
|
To generate scripts, load the program into GHCI and execute as follows:
|
||
|
```
|
||
|
cd src
|
||
|
ghci
|
||
|
:load Cdl/SampleCows.hs Cdl/Codegen.hs Cdl/Cow.hs
|
||
|
:module Cdl.SampleCows Cdl.Codegen Cdl.Cow
|
||
|
outputCow "test.py" 0.1 (1, 1, Coord 0 0, squareCow)
|
||
|
```
|
||
|
|
||
|
In `outputCow`, the `0.1` is the sampling frequency (how often
|
||
|
the database will receive mock data from the cows), the first `1` is
|
||
|
the collar ID sending the data, the second `1` is the cow's walking speed (in meters/second),
|
||
|
the `Coord 0 0` is the initial longitude and latitude of the cow, and `squareCow` is
|
||
|
the cow's actions described above.
|
||
|
|
||
|
Note that the script relies on being in the same directory as the `server` repository
|
||
|
containing our database model.
|