diff --git a/src/main/scala/TopSongs/TopSongs.scala b/src/main/scala/TopSongs/TopSongs.scala index 149db0d..18bd73d 100644 --- a/src/main/scala/TopSongs/TopSongs.scala +++ b/src/main/scala/TopSongs/TopSongs.scala @@ -6,10 +6,33 @@ trait Person { val name: String } -case class Artist(name: String) extends Person +case class Singer(name: String) extends Person + case class Writer(name: String) extends Person + case class Producer(name: String) extends Person -class Album(title: String, label: String) + +// The parametrized type Artist can be a Singer, a Writer or a Producer +// They do a different creation action +class Artist[A <: Person](val person: A) { + def create(): String = { + person match { + case s: Singer => s"${s.name} sing" + case w: Writer => s"${w.name} write" + case p: Producer => s"${p.name} produce" + case _ => s"${person.name} create" + } + } +} + + +// Defined a MusicGender as en enum +enum MusicGenre: + case Rock, Soul, Blues, Folk, Funk, Reggae, HipHop, NewWave, Electro, Metal + +// Define an Album with a union between a String and a MusicGenre +class Album(title: String, label: String, genre: String|MusicGenre) + class Streak(val s: String) { val streak: Option[Int] = { val regex = "\\d+".r @@ -23,8 +46,9 @@ class Streak(val s: String) { } } } + class Position(val p: String) { - val position: Option[Int] = { + val pos: Option[Int] = { val regex = "\\d+".r regex.findFirstIn(p) match { case Some(value) => Some(Integer.parseInt(value)) @@ -33,15 +57,24 @@ class Position(val p: String) { } } +// Defined a type alias Rank which is a tuple of Streak and Position +// Streak and Position are linked together, it's why there are regrouped in the Rank type alias +type Rank = (Streak, Position) + +// Defined an intersection type of Artist & Writer & Producer +// Defined with an alias : God +// It's a way to define a type that is a combination of other types +// If an Artist is also a Writer and a Producer, it's basically a God of the music +type God = Singer & Writer & Producer + class Song( val title: String, val description: Option[String], - val artist: List[Artist], - val writer: List[Writer], - val producer: List[Producer], + val singer: List[Artist[Singer]], + val writer: List[Artist[Writer]], + val producer: List[Artist[Producer]], val album: Option[Album], - val streak: Streak, - val position: Position + val rank: Rank ) @@ -50,12 +83,27 @@ case class TopSongs(songs: List[Song] = List()) { TopSongs(song :: songs) } def printSongs(): Unit = { - songs.foreach(song => println( - s"${song.title} by ${song.artist.map(_.name).mkString(", ")} " + - s"produced by ${song.producer.map(_.name).mkString(", ")} " + - s"spent ${song.streak.streak.getOrElse("no")} weeks " + - s"on the charts on Pos. ${song.position.position.getOrElse("NA")}" - )) + songs.foreach(song => { + val title = song.title + val singer = song.singer + val producers = song.producer.map(_.create()).mkString(", ") + val streak = song.rank._1.streak.getOrElse("no") + val pos = song.rank._2.pos.getOrElse("NA") + + if (singer.exists(a => { + a.isInstanceOf[God] + })) { + println(s"$title by God ${singer.map(_.person.name).mkString(", ")} spent $streak weeks on the charts on Pos. $pos") + } else { + println( + s"$title by ${singer.map(_.person.name).mkString(", ")}. " + + s"$producers this song that " + + s"spent $streak weeks " + + s"on the charts on Pos. $pos" + ) + } + + }) } } @@ -66,15 +114,22 @@ case class TopSongs(songs: List[Song] = List()) { val reader = CSVReader.open(new File("src/main/resources/songs.csv")) val allRows = reader.allWithHeaders() for (row <- allRows) { + val title = row("title") + val description = row("description") + val singer = List(Artist[Singer](Singer(row("artist")))) + val writers = List(Artist[Writer](Writer(row("writers")))) + val producers = List(Artist[Producer](Producer(row("producer")))) + val album = Some(Album(row("appears on"), "NA", null)) + val rank = (Streak(row("streak")), Position(row("position"))) + val s = Song( - title = row("title"), - description = Some(row("description")), - artist = List(Artist(row("artist"))), - writer = List(Writer(row("writers"))), - producer = List(Producer(row("producer"))), - album = Some(Album(row("appears on"), "NA")), - streak = Streak(row("streak")), - position = Position(row("position")) + title = title, + description = Some(description), + singer = singer, + writer = writers, + producer = producers, + album = album, + rank = rank ) // add the song to the TopSongs object @@ -82,5 +137,7 @@ case class TopSongs(songs: List[Song] = List()) { } reader.close() + val foo: Boolean = topSongs.songs.exists(s => s.rank._1.streak.contains(1)) + // print the songs topSongs.printSongs()