diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4bc8535 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +elm-stuff diff --git a/README.md b/README.md index e70026e..0f62f83 100644 --- a/README.md +++ b/README.md @@ -80,3 +80,86 @@ We want to see: ## Submitting your solution Please submit your solution as a PR including some nice commits for challenge 1 and the rest in Markdown. + +# Answers - Suzanne Wood + +# 1. Deduplicate + +To run tests: +`npx elm-test` + +# 2. Cars + +Schema for tables: + + CREATE TABLE `car` ( + `id` int not null PRIMARY KEY, + `lender_id` int not null + ); + CREATE TABLE `car_availability` ( + `id` int not null PRIMARY KEY, + `car_id` int not null, + `from` datetime not null, + `to` datetime not null + ); + CREATE TABLE `user` ( + `id` int not null PRIMARY KEY + ); + CREATE TABLE `user_bookings` ( + `id` int not null PRIMARY KEY, + `user_id` int not null, + `car_id` int not null, + `from` datetime not null, + `to` datetime not null + ); + +I would also add indices depending on what common queries are needed. + + + + +Relations: +- each card belongs to a lender, a lender can lend multiple cars +- car availability has slots which do not touch or overlap (these can be combined if they come up when adding) +- no two user bookings for the same car_id can overlap + +Query for finding available cars for a timeslot 'from', 'to' (pseudocode) + + select c.id as car_id, count(ub.id where ub.id is not null) as overlapping_bookings + from cars c join + car_availability ca on c.id = ca.car_id join + user_bookings ub on ( + ub.id = ca.user_id and + !((ub.from <= {from} and ub.to <= {to}) or + (ub.from >= {from} and ub.to >= {to})) # excluding non-overlapping slots + ) + where + ca.from <= {from} and ca.to >= {to} + group by c.id + having count(ub.id) = 0 + +Comparison with other solutions: +You could simplify the approach using discrete timeslots whether by hour, by day etc - but the one I outlined allows high flexibility of timeslots. I also considered storing available timeslots with bookings subtracted, already showing a complete availability picture but it becomes messy to manage, makes more sense to keep availability and bookings seperate and then layer them up when querying + + + +# 3. Frontops + +I would use a docker file with two FROM statements e.g. + + FROM xxxx as staging + WORKDIR xxx + RUN xxx + COPY xxx + RUN xxx + + FROM xxxx as production + WORKDIR xxx + RUN xxx + COPY --from=staging + RUN xxx + +This also enables deploying just staging by e.g. running `docker build --target staging ` +I would have config files with ENV variables for each environment so when running for a different FQDN in eg staging I would change in the staging config file + +For a change in API, it depends how the API change is rolled out. For example, if it was via a new FQDN I'd change that and any code changes needed for staging only and once tested move to production. If the API change is known to be sudden with no way to roll over, if possible I'd make the code be able to handle both versions for the transition. diff --git a/elm.json b/elm.json new file mode 100644 index 0000000..7468f5e --- /dev/null +++ b/elm.json @@ -0,0 +1,28 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/browser": "1.0.2", + "elm/core": "1.0.5", + "elm/html": "1.0.0" + }, + "indirect": { + "elm/json": "1.1.3", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.2" + } + }, + "test-dependencies": { + "direct": { + "elm-explorations/test": "1.2.2" + }, + "indirect": { + "elm/random": "1.0.0" + } + } +} diff --git a/src/Deduplicator.elm b/src/Deduplicator.elm new file mode 100644 index 0000000..100375a --- /dev/null +++ b/src/Deduplicator.elm @@ -0,0 +1,15 @@ +module Deduplicator exposing (deduplicate) + + +deduplicate : List String -> List String +deduplicate words = + List.foldl addToListIfNotMatch [] (List.sort words) + +addToListIfNotMatch : String -> List String -> List String +addToListIfNotMatch element partialList = + if Just element /= List.head partialList then + element :: partialList + + else + partialList + diff --git a/tests/DeduplicatorTest.elm b/tests/DeduplicatorTest.elm new file mode 100644 index 0000000..75cb247 --- /dev/null +++ b/tests/DeduplicatorTest.elm @@ -0,0 +1,35 @@ +module DeduplicatorTest exposing (..) + +import Deduplicator +import Expect +import Test exposing (..) + + +suite : Test +suite = + describe "The Deduplicator module" + [ describe "Deduplicator.deduplicate" + -- Nest as many descriptions as you like. + [ test "returns an identical list for an list of length 1" <| + \_ -> + let + words = + [ "fish" ] + in + Expect.equal words (Deduplicator.deduplicate words) + , test "returns an identical list for an list of length 0" <| + \_ -> + let + words = + [] + in + Expect.equal words (Deduplicator.deduplicate words) + , test "returns a deduplicated list" <| + \_ -> + let + words = + [ "fish", "chip", "egg", "fish", "egg" ] + in + Expect.equal [ "fish", "egg", "chip" ] (Deduplicator.deduplicate words) + ] + ]