# Lab 1: SBT & Rational
> **Due Date**: 30.01.2020 9:00 AM
## Stage 1 – Simple Build Tool (sbt)
1. Download and Install IntelliJ IDEA. [Link](https://www.jetbrains.com/idea/download/)
2. Download and Install the Scala Plugin: [Link](https://plugins.jetbrains.com/plugin/1347-scala)

<!-- 3. Congratz! You found an easter egg! Contact your TA for bonus points -->
4. Create a new sbt project using these versions:
- Java Version: `1.8`
- Scala Version: `2.12.10`
- sbt Version: `1.2.8`
Make sure that you selected "Use sbt shell for imports and build".

5. Create a package `<your-name>.<your-surname>` in the directory `src/main/scala`.
6. Create a file `Rational.scala` in that package.
## Stage 2 – Rational
```scala
package <your-name>.<your-surname>
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
def + (that: Rational): Rational = new Rational(numer * that.denom + that.numer * denom, denom * that.denom)
def + (i: Int): Rational = ???
def - (that: Rational): Rational = new Rational(numer * that.denom - that.numer * denom, denom * that.denom)
def - (i: Int): Rational = ???
def * (that: Rational): Rational = new Rational(numer * that.numer, denom * that.denom)
def * (i: Int): Rational = ???
def / (that: Rational): Rational = new Rational(numer * that.denom, denom * that.numer)
def / (i: Int): Rational = ???
override def toString = numer + "/" + denom
private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
}
```
Tasks:
1. Introduce a companion object `Rational` and move the `gcd` method into that object.
2. Make the constructor of `Rational` private and create a method called `apply` in the companion object, which will call the constructor.
3. Calculate the GCD of the numerator and the denominator in the `apply` method and invoke the constructor of `Rational` inside `apply` with normalized arguments.
4. Implement `def == (other: Rational): Boolean` method to the `Rational` class. Make sure that it outputs `true` for `Rational(4, 2)` and `Rational(2, 1)`. At this stage two objects should be equal iff all their member fields are equal.
## Stage 3 – Tests
Now we are going to write some unit-tests. Open your `build.sbt` file and add the following line:
```scala
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % Test
```
This line brings the [ScalaTest](http://www.scalatest.org/) framework as a dependency of your project. It will be used to create and run test suites for your code.
Similarly to Stage 1, create a package `<your-name>.<your-surname>` in the directory `src/test/scala`. Notice the directory `test` – it will contain all test-related code and resources. The ScalaTest framework will be unavailable in the main code.
Create a file `RationalSpec.scala` in the `test` section and paste the following code:
```scala
package <your-name>.<your-surname>
import org.scalatest.{FlatSpec, Matchers}
class RationalSpec extends FlatSpec with Matchers {
"==" should "be correct for 2/1 and 4/2" in {
val isEqual = Rational(2, 1) == Rational(4, 2)
isEqual shouldBe true
}
}
```
You can run the spec via your IDE – notice the green next to class name and individual tests, as well as via your sbt shell – run `test` command in the panel `sbt shell` below. Try to do it both ways.
Task:
- Implement 2 tests for any desired operations of `Rational`
## Stage 4 - REPL
Scala has a convinient REPL that you can use to test your code. To start the REPL with all the dependencies of sbt project - run `console` command in the sbt shell.
Tasks:
- Import your `Rational` implementation into the scope of REPL
- Create two instances and perform any operation
- Screenshot the REPL panel with all entered instructions and outputs
## Deliverables
1. zip archive with your sbt project – 0.5 points
2. screenshot of your REPL output – 0.5 points