Last active
December 16, 2015 15:39
-
-
Save robertpi/5457903 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ParkingMeterKata | |
open System | |
type Coin = | |
| TenCents = 10 | |
| TwentyCents = 20 | |
| FiftyCents = 50 | |
| OneEuro = 100 | |
| TwoEuro = 200 | |
let amountOfCoin (coin: Coin) = | |
Convert.ToDecimal (coin |> int) / 100m | |
let amountOfCoins (coins: seq<Coin>) = | |
coins |> Seq.map amountOfCoin |> Seq.sum | |
let priceTable = | |
[ 8.M, 600M | |
5.M, 300M | |
3.M, 120M | |
2.M, 60M | |
1.M, 20M ] | |
let getMinutesBought (amount: Decimal) = | |
let priceRange = priceTable |> Seq.tryFind (fun (price, time) -> amount >= price) | |
match priceRange with | |
| Some (price, time) -> (amount / price) * time | |
| None -> failwith "Not enough" | |
let isExcludeDay (date: DateTime) = | |
date.DayOfWeek = DayOfWeek.Sunday | |
|| date.Month = 8 | |
// TODO public holidates | |
let minutesInADay = 600M | |
let payingDays (startDate: DateTime) = | |
let allDates = Seq.initInfinite (fun x -> startDate.AddDays( x |> float)) | |
allDates |> Seq.filter (fun x -> not (isExcludeDay x)) | |
let startPayingNextDay (startDate: DateTime) = | |
startDate.Hour > 19 | |
let addTime (startDate: DateTime) (minutes: Decimal) = | |
let days = | |
(Math.Floor (minutes / minutesInADay)|> int) + | |
(if startPayingNextDay startDate then 1 else 0) | |
let remainingMinutes = minutes % minutesInADay |> float | |
let date = if days > 0 then Seq.nth days (payingDays startDate) else startDate | |
let dateWithAllMinsAdded = date.AddMinutes(remainingMinutes) | |
if dateWithAllMinsAdded.Hour > 19 then | |
let nextDay = Seq.nth 1 (payingDays date) | |
let nextDayAt9 = nextDay.Date.AddHours(9.) | |
let remainingMins = | |
dateWithAllMinsAdded - date.Date.AddHours(19.) | |
nextDayAt9.Add( remainingMins) | |
else | |
dateWithAllMinsAdded | |
let calcuateEndDateFromAmount (time: DateTime) (amount: Decimal) = | |
let minutes = getMinutesBought amount | |
addTime time minutes | |
let calcumateEndDateFromCoins (time: DateTime) (coins: seq<Coin>) = | |
calcuateEndDateFromAmount time (coins |> amountOfCoins) | |
//[<EntryPoint>] | |
//let main argv = | |
// printfn "%A" argv | |
// 0 // return an integer exit code |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment