Skip to content

Commit

Permalink
Stamp and LTV
Browse files Browse the repository at this point in the history
  • Loading branch information
keynmol committed Mar 11, 2024
1 parent ad22683 commit 51a07dc
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 7 deletions.
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.9.2
sbt.version=1.9.9
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.13.2")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.14.0")
61 changes: 56 additions & 5 deletions src/main/scala/example/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import org.scalajs.dom
import scala.scalajs.js.annotation.JSImport

import scalajs.js
import java.text.DecimalFormat
import org.scalajs.dom.intl.NumberFormat
import com.raquo.airstream.core.Observable

trait ChartDataset extends js.Any:
var label: String
Expand Down Expand Up @@ -42,10 +45,45 @@ case class Settings(
val effectiveMonthlyRate = rate / 100 / 12
val thing = math.pow(1 + effectiveMonthlyRate, months)
loanAmount * effectiveMonthlyRate * thing / (thing - 1)

def stampDuty: Double =
val firstTimeBuyerRelief = housePrice <= 625_000
val bands =
if !firstTimeBuyerRelief then
List(
250_000 -> 0.0,
925_000 -> 0.05,
1_500_000 -> 0.10,
100_000_000 -> 0.12
)
else List(425_000 -> 0.0, 625_000 -> 0.05)

val augmentedBands =
bands
.prepended(0 -> 0.0)
.zip(bands)
.map:
case ((st, _), (ed, rate)) =>
(st, ed) -> rate

augmentedBands
.map:
case ((from, to), rate) =>
if from < housePrice then
val length = to - from
val baseline = (housePrice - from)
if baseline > length then length * rate
else baseline * rate
else 0.0
.sum

end stampDuty

def LTVPercent = 100 * (loanAmount / housePrice)
end Settings

def app =
val housePrice = Var(400_000.0)
val housePrice = Var(800_000.0)
val deposit = Var(50_000.0)
val durationYears = Var(25)
val rate = Var(6.0)
Expand All @@ -55,8 +93,12 @@ def app =
val calculation =
combined.map(_.monthlyPayment)

inline def poundValue(source: Source[Double]) =
span(color.maroon, child.text <-- source.toObservable.map(d => f"£$d%.2f"))
val numberFormat = NumberFormat("en-GB")

inline def poundValue(source: Observable[Double]) =
val nn =
source.toObservable.map(value => "£" + numberFormat.format(value.floor))
span(color.maroon, child.text <-- nn)

val sliders = div(
width := "50%",
Expand All @@ -71,7 +113,7 @@ def app =
_.showTickmarks := true,
_.events.onInput.map(_.target.value) --> rate
),
h1("House price: ", poundValue(housePrice)),
h1("House price: ", poundValue(housePrice.signal)),
Slider(
_.min := 100_000,
_.max := 1_200_000,
Expand All @@ -82,7 +124,7 @@ def app =
_.showTickmarks := true,
_.events.onInput.map(_.target.value) --> housePrice
),
h1("Deposit: ", poundValue(deposit)),
h1("Deposit: ", poundValue(deposit.signal)),
Slider(
_.min := 10_000,
_.max := 500_000,
Expand Down Expand Up @@ -117,6 +159,14 @@ def app =
)
val chart = div(
width := "50%",
h2(
b("LTV: "),
child.text <-- combined.map(_.LTVPercent.toString() + "%")
),
h2(
b("Stamp duty: "),
poundValue(combined.map(_.stampDuty))
),
canvasTag( // onMountUnmount callback to bridge the Laminar world and the Chart.js world
onMountUnmountCallback(
// on mount, create the `Chart` instance and store it in optChart
Expand Down Expand Up @@ -149,6 +199,7 @@ def app =
}
)
)

div(
h1(
"The lolno calculator - why you will never afford a mortgage in the UK"
Expand Down

0 comments on commit 51a07dc

Please sign in to comment.