Skip to content

Instantly share code, notes, and snippets.

@robertpi
Last active December 16, 2015 15:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robertpi/5457903 to your computer and use it in GitHub Desktop.
Save robertpi/5457903 to your computer and use it in GitHub Desktop.
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