This is the "take home test" answer I returned in 2016 when interviewing for Agricool. Below is the README I provided, unedited, with original typos or mistakes :)
--
This program analyzes temperature & humidity time-series from a grow-house to detect conditions opportune to the development of diseases, based on a set of rules.
- The program is written in Kotlin, an easy-to-read, concise and safe general purpose language for the JVM, that I felt was suited for such an exercise. Also, it's very fun to write in.
- I've designed the solution so that it would be simple to adapt and run "live". The main component, the "supervisor" exposes an observable stream of hot alerts using RxJava.
- The supervisor mutable state is isolated in its own immutable structure that gets copied and updated when state changes. This is similar in nature to the state of a React component ; it helps to reason about the program and its data, makes it predictable and less prone to unexpected side-effects.
- I've assumed sensor values are pushed to the system in natural time order
- I've assumed a sensor value is "valid" until the next one received for that sensor
- I've assumed all dates are given at Paris time
Here's the project structure overview. Some files are not listed for clarity.
src
├── main
│ ├── kotlin
│ │ └── exercise
│ │ ├── app.kt # Entry point of the app. CLI parsing, CSV loading, etc.
│ │ ├── model.kt # Domain models the supervisor manipulates
│ │ ├── rules.kt # The actual rules evaluated by the program (oïdium, botrytis)
│ │ ├── supervisor.kt # The core supervisor engine that detects diseases conditions
│ │ └── utils.kt # Various utils
│ └── resources # CSV files directory
└── test
├── kotlin
│ └── exercise
│ ├── all-tests.kt # Test suite with all tests
│ └── test-utils.kt # Unit test helpers
└── resources
└── fixtures # Test fixtures
-
In this version and for the sake of the exercise, the supervisor emits an alert when a "situation" is finished. In a real system, of course the alert must be emitted as soon as the time threshold for the situation is reached.
-
Here the rules are declared formally by instantiating a rule object. It would be better to propose a rule builder or a DSL to express rules and their expressions in simpler fashion. For example such a DSL could allow to express rules the following way, in a type-safe manner :
"Botrytis" { when(temperature > 15) when(temperature < 25) when(humity > 90) for(600 minutes) }
You will need a JVM and Gradle to build the program from sources.
You can build the app using :
gradle build
And to run directly the entry-point that analyses the sample lab files provided :
gradle run
You can run unit tests using :
gradle cleanTest test
Docker image is published at https://hub.docker.com/r/jvelo/ac-exercise/
Run with default provided log files :
docker run jvelo/ac-exercise
Run with custom log files fetched from HTTP URIs :
docker run jvelo/ac-exercise --temperature=http://pastebin.com/raw/GaFGfpPe --humidity=http://pastebin.com/raw/T3uTS4Sj
The docker image is also built with gradle, using :
gradle distDocker