import io.circe.parser.decode import io.circe.syntax.* import io.gitlab.myrolabs.family.data.InitialSeeding import io.gitlab.myrolabs.family.model.* import cats.syntax.functor.* import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} import io.circe.syntax.* import io.circe.{Decoder, Encoder} import cats.syntax.functor.* import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} import io.circe.syntax.* import io.circe.{Decoder, Encoder} sealed trait StorageItem { def uid: String def document: Doc def comment: String def duplicates: Seq[String] } object StorageItem { implicit val encoder: Encoder[StorageItem] = Encoder.instance { case n@BirthCertificate(_, _, _, _, _) => n.asJson case n@BaptismRecord(_, _, _, _, _, _, _) => n.asJson case n@WeddingRecord(_, _, _, _, _, _, _, _, _) => n.asJson case n@DeathRecord(_, _, _, _, _, _, _) => n.asJson case n@Tomb(_, _, _, _, _) => n.asJson case n@ResidenceRecord(_, _, _, _, _) => n.asJson case n@Letter(_, _, _, _, _, _) => n.asJson case n@PersonalDocument(_, _, _, _, _, _) => n.asJson } implicit val decoder: Decoder[StorageItem] = List[Decoder[StorageItem]]( Decoder[BirthCertificate].widen, Decoder[BaptismRecord].widen, Decoder[WeddingRecord].widen, Decoder[DeathRecord].widen, Decoder[Tomb].widen, Decoder[ResidenceRecord].widen, Decoder[Letter].widen, Decoder[PersonalDocument].widen, ).reduceLeft(_ or _) } case class BirthCertificate(uid: String, birth: Birth, document: Doc, comment: String, duplicates: Seq[String]) extends StorageItem object BirthCertificate { implicit val decoder: Decoder[BirthCertificate] = deriveDecoder[BirthCertificate] implicit val encoder: Encoder[BirthCertificate] = deriveEncoder[BirthCertificate] } case class BaptismRecord(uid: String, birth: Birth, baptismDate: Option[Date], godparents: Seq[Name], document: Doc, comment: String, duplicates: Seq[String]) extends StorageItem object BaptismRecord { implicit val decoder: Decoder[BaptismRecord] = deriveDecoder[BaptismRecord] implicit val encoder: Encoder[BaptismRecord] = deriveEncoder[BaptismRecord] } case class WeddingRecord(uid: String, groom: Person, bride: Person, weddingPlace: Option[Place], weddingDate: Option[Date], godparents: Seq[Name], document: Doc, comment: String, duplicates: Seq[String]) extends StorageItem object WeddingRecord { implicit val decoder: Decoder[WeddingRecord] = deriveDecoder[WeddingRecord] implicit val encoder: Encoder[WeddingRecord] = deriveEncoder[WeddingRecord] } case class DeathRecord(uid: String, death: Death, related: Option[Name], reason: String, document: Doc, comment: String, duplicates: Seq[String]) extends StorageItem object DeathRecord { implicit val decoder: Decoder[DeathRecord] = deriveDecoder[DeathRecord] implicit val encoder: Encoder[DeathRecord] = deriveEncoder[DeathRecord] } case class Tomb(uid: String, death: Death, document: Doc, comment: String, duplicates: Seq[String]) extends StorageItem object Tomb { implicit val decoder: Decoder[Tomb] = deriveDecoder[Tomb] implicit val encoder: Encoder[Tomb] = deriveEncoder[Tomb] } case class ResidenceRecord(uid: String, residents: Seq[Individual], document: Doc, comment: String, duplicates: Seq[String]) extends StorageItem object ResidenceRecord { implicit val decoder: Decoder[ResidenceRecord] = deriveDecoder[ResidenceRecord] implicit val encoder: Encoder[ResidenceRecord] = deriveEncoder[ResidenceRecord] } case class Letter(uid: String, title: String, correspondents: Seq[LegalEntity], document: Doc, comment: String, duplicates: Seq[String]) extends StorageItem object Letter { implicit val decoder: Decoder[Letter] = deriveDecoder[Letter] implicit val encoder: Encoder[Letter] = deriveEncoder[Letter] } /** Fallback for other types of documents */ case class PersonalDocument(uid: String, title: String, person: Name, document: Doc, comment: String, duplicates: Seq[String]) extends StorageItem object PersonalDocument { implicit val decoder: Decoder[PersonalDocument] = deriveDecoder[PersonalDocument] implicit val encoder: Encoder[PersonalDocument] = deriveEncoder[PersonalDocument] } trait Person { def name: Name } object Person { def livingIn(name: String, residence: Place, birthDate: Date, comment: String): Person = Resident(Name(name), residence, birthDate, comment) def bornAt(name: String, birthPlace: Place, birthDate: Date, comment: String): Person = Individual(Name(name), Some(birthPlace), birthDate, comment) def phoneBookList(residents: Seq[(String, Date, String)]): Seq[Individual] = residents.map(t => Individual(Name(t._1), None, t._2, t._3)) def confessionList(documentYear: Int, residents: Seq[(String, Int, String)]): Seq[Individual] = residents.map(t => Individual(Name(t._1), None, Date.circa(String.valueOf(documentYear - t._2)), t._3)) def revisionList(documentYear: Int, residents: Seq[(String, Place, Int, String)]): Seq[Individual] = residents.map(t => Individual(Name(t._1), Some(t._2), Date.circa(String.valueOf(documentYear - t._3)), t._4)) implicit val encoder: Encoder[Person] = Encoder.instance { case r@Resident(_, _, _, _) => r.asJson case s@Individual(_, _, _, _) => s.asJson } implicit val decoder: Decoder[Person] = List[Decoder[Person]](Decoder[Resident].widen, Decoder[Individual].widen).reduceLeft(_ or _) } /** Used for church wedding records */ case class Resident(name: Name, residence: Place, birthDate: Date, comment: String) extends Person object Resident { implicit val decoder: Decoder[Resident] = deriveDecoder[Resident] implicit val encoder: Encoder[Resident] = deriveEncoder[Resident] } /** Used in residence records and in marriage certificate */ case class Individual(name: Name, birthPlace: Option[Place], birthDate: Date, comment: String) extends Person object Individual { implicit val decoder: Decoder[Individual] = deriveDecoder[Individual] implicit val encoder: Encoder[Individual] = deriveEncoder[Individual] } import io.circe.{Decoder, Encoder} import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} // TODO: attachments, transcript? case class Doc(tags: Seq[String], repository: Option[Repo], place: Option[Place], date: Option[Date]) object Doc { def birth(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("birth", "свідоцтво про народження"), repository, place, date) def baptism(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("birth", "baptism", "метричний запис"), repository, place, date) def mrgCert(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("wedding", "свідоцтво про шлюб"), repository, place, date) def mrgRec(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("wedding", "метричний запис"), repository, place, date) def mrgPreRec(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("wedding", "шлюбний обшук"), repository, place, date) def death(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("death", "метричний запис"), repository, place, date) def tomb: Doc = Doc(Seq("death", "tomb"), None, None, None) def rsdConfession(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("residence", "метричний запис"), repository, place, date) def rsdCensus(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("residence", "перепис"), repository, place, date) def rsdRevision(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("residence", "ревізія"), repository, place, date) def rsdPhoneBook(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("residence", "телефонний довідник"), repository, place, date) def letter(repository: Option[Repo], place: Option[Place], date: Option[Date]): Doc = Doc(Seq("letter"), repository, place, date) implicit val decoder: Decoder[Doc] = deriveDecoder[Doc] implicit val encoder: Encoder[Doc] = deriveEncoder[Doc] } import io.circe.{Decoder, Encoder} import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} case class Birth(child: Name, father: Option[Name], mother: Option[Name], place: Option[Place], date: Option[Date]) object Birth { def apply(child: String, father: Option[String], mother: Option[String], place: Option[Place], date: Option[Date]): Birth = Birth(Name(child), father.map(n => Name(n)), mother.map(n => Name(n)), place, date) implicit val decoder: Decoder[Birth] = deriveDecoder[Birth] implicit val encoder: Encoder[Birth] = deriveEncoder[Birth] } import cats.syntax.functor.* import io.circe.generic.auto.* import io.circe.syntax.* import io.circe.{Decoder, Encoder} import java.time.{LocalDate, Year, YearMonth} import scala.util.Try sealed trait Date case class DateRange(from: InternalDate, to: InternalDate) extends Date case class SingleDate(value: InternalDate, approximate: Boolean) extends Date sealed trait InternalDate case class YearOnly(year: Year) extends InternalDate case class YearAndMoth(yearMonth: YearMonth) extends InternalDate case class FullDate(fullDate: LocalDate) extends InternalDate object Date { def range(from: String, to: String): DateRange = DateRange(parse(from), parse(to)) def circa(d: String): SingleDate = SingleDate(parse(d), approximate = true) def on(d: String): SingleDate = SingleDate(parse(d), approximate = false) private def parse(str: String): InternalDate = Seq( Try(LocalDate.parse(str)).map(FullDate), Try(YearMonth.parse(str)).map(YearAndMoth), Try(Year.parse(str)).map(YearOnly) ).find(_.isSuccess) .getOrElse(throw new RuntimeException(s"Can't parse $str to date!")) .get // indicate parsing error, but not data absence implicit val encoder: Encoder[Date] = Encoder.instance { case r @ DateRange(_, _) => r.asJson case s @ SingleDate(_, _) => s.asJson } implicit val decoder: Decoder[Date] = List[Decoder[Date]](Decoder[DateRange].widen, Decoder[SingleDate].widen).reduceLeft(_ or _) implicit val encode: Encoder[InternalDate] = Encoder.instance { case r @ YearOnly(_) => r.asJson case s @ YearAndMoth(_) => s.asJson case s @ FullDate(_) => s.asJson } implicit val decode: Decoder[InternalDate] = List[Decoder[InternalDate]]( Decoder[YearOnly].widen, Decoder[YearAndMoth].widen, Decoder[FullDate].widen ).reduceLeft(_ or _) } import io.circe.{Decoder, Encoder} import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} case class Death(person: Name, place: Option[Place], birthDate: Option[Date], deathDate: Option[Date]) object Death { def apply(person: String, place: Place, birthDate: Date, deathDate: Date): Death = Death(Name(person), Some(place), Some(birthDate), Some(deathDate)) implicit val decoder: Decoder[Death] = deriveDecoder[Death] implicit val encoder: Encoder[Death] = deriveEncoder[Death] } import cats.syntax.functor.* import io.circe.generic.auto.* import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} import io.circe.syntax.* import io.circe.{Decoder, Encoder} trait LegalEntity object LegalEntity { implicit val encoder: Encoder[LegalEntity] = Encoder.instance { case r @ Org(_) => r.asJson case s @ Name(_, _, _) => s.asJson } implicit val decoder: Decoder[LegalEntity] = List[Decoder[LegalEntity]](Decoder[Org].widen, Decoder[Name].widen).reduceLeft(_ or _) } case class Org(name: String) extends LegalEntity case class Name(surname: String, name: String, paternal: Option[String]) extends LegalEntity object Name { def apply(fullName: String): Name = { val parsed = fullName.split(" ") parsed.size match { case 2 => Name(parsed.head, parsed.last, None) case 3 => Name(parsed.head, parsed(1), parsed.lastOption) case _ => throw new RuntimeException(s"Can't parse name $fullName to surname, name and paternal") // indicate parsing error, but not data absence } } implicit val decoder: Decoder[Name] = deriveDecoder[Name] implicit val encoder: Encoder[Name] = deriveEncoder[Name] } import cats.syntax.functor.* import io.circe.generic.auto.* import io.circe.syntax.* import io.circe.{Decoder, Encoder} sealed trait Place case class NamedPlace(name: String) extends Place case class GeoPlace(lat: Double, lon: Double, name: String) extends Place object Place { def geo(latLon: String, name: String): GeoPlace = { val parsed = latLon.split(",") parsed.size match { case 2 => GeoPlace(parsed.head.trim.toDouble, parsed.last.trim.toDouble, name) case _ => throw new RuntimeException(s"Can not parse $latLon to geo coordinates!") // indicate parsing error, but not data absence } } def named(name: String): NamedPlace = name.isEmpty match { case false => NamedPlace(name) case true => throw new RuntimeException("Empty place name! Use None if place is not specified") // indicate parsing error, but not data absence } def zh: Place = Place.named("м. Житомир") def shchyh: Place = Place.named("с. Щигліївка") def lutsk: Place = Place.named("м. Луцьк") def krop: Place = Place.named("с. Кропивня") def vilnaChurch: Place = Place.named("Церква св. Михаїла с. Вільня") def minijky: Place = Place.named("с. Минійки") def starosilChurch: Place = Place.named("Церква Різдва Богородиці с. Старосільці") def may: Place = Place.named("с. Перше Травня") implicit val encode: Encoder[Place] = Encoder.instance { case n@NamedPlace(_) => n.asJson case g@GeoPlace(_, _, _) => g.asJson } implicit val decode: Decoder[Place] = List[Decoder[Place]](Decoder[NamedPlace].widen, Decoder[GeoPlace].widen).reduceLeft(_ or _) } import cats.syntax.functor.* import io.circe.generic.auto.* import io.circe.syntax.* import io.circe.{Decoder, Encoder} sealed trait Repo case class Archive(name: String, callNo: String, pages: Option[String]) extends Repo case class Repository(location: String) extends Repo object Repo { def cdiak(callNo: String, pages: Option[String] = None): Archive = Archive("ЦДІАК", callNo, pages) def dazho(callNo: String, pages: Option[String] = None): Archive = Archive("ДАЖО", callNo, pages) def dako(callNo: String, pages: Option[String] = None): Archive = Archive("ДАКО", callNo, pages) def camo(callNo: String, pages: Option[String] = None): Archive = Archive("ЦАМО РФ", callNo, pages) def home: Repository = Repository("Домашній архів") def apply(location: String): Repository = Repository(location) implicit val encodeEvent: Encoder[Repo] = Encoder.instance { case n@Archive(_, _, _) => n.asJson case g@Repository(_) => g.asJson } implicit val decodeEvent: Decoder[Repo] = List[Decoder[Repo]](Decoder[Archive].widen, Decoder[Repository].widen).reduceLeft(_ or _) } val allData: Seq[StorageItem] = Seq( BirthCertificate( "A001", Birth("FOO BAR BAZ", "FOO BAR BAZ", "FOO BAR BAZ", Place.zh, Date.on("2019-05-31")), Doc.birth(Repo.home, Place.zh, Date.on("2019-11-18")), "повторно", Seq() ), PersonalDocument("A002", "Свідоцтво про зміну імені", Name("FOO BAR BAZ"), Doc(Seq("birth"), Repo.home, Place.zh, Date.on("2019-12-18")), "", Seq()), BirthCertificate( "A003", Birth("FOO BAR BAZ", "FOO BAR BAZ", "РFOO BAR BAZ", Place.zh, Date.on("1984-04-27")), Doc.birth(Repo.home, Place.zh, Date.on("1984-05-12")), "недійсне", Seq() ), PersonalDocument("A004", "Вітання з новонародженим", Name("FOO BAR BAZ"), Doc(Seq("birth"), Repo.home, Place.zh, Date.circa("1984")), "", Seq()), BaptismRecord( "A005", Birth("FOO BAR BAZ", None, None, None, None), Date.on("1984-04-17"), Seq(), Doc(Seq("baptism"), Repo.home, Place.geo("50.23622104582598, 28.70584145545469", "Церква Св. Миколи"), Date.circa("1984")), "", Seq() ), BirthCertificate( "A006", Birth("FOO BAR BAZ", "FOO BAR BAZ", "FOO BAR BAZ", Place.shchyh, Date.on("1960-10-31")), Doc.birth(Repo.home, Place.shchyh, Date.on("1961-01-02")), "", Seq() ), BirthCertificate( "A007", Birth("FOO BAR BAZ", "FOO BAR BAZ", "FOO BAR BAZ", Place.lutsk, Date.on("1995-07-21")), Doc.birth(Repo.home, Place.lutsk, Date.on("1995-07-28")), "", Seq() ), BaptismRecord( "A008", Birth("FOO BAR BAZ", "FOO BAR BAZ", "РFOO BAR BAZ", Place.krop, Date.on("1914-02-21")), Date.on("1914-03-02"), Seq(), Doc.baptism(Repo.dazho("1-77-1715"), Place.vilnaChurch, None), "Хрещені записані нерозбірливо", Seq() ), BaptismRecord( "A009", Birth("FOO BAR BAZ", "FOO BAR BAZ", "FOO BAR BAZ", Place.shchyh, Date.on("1897-04-21")), Date.on("1897-04-19"), Seq(Name("FOO BAR BAZ"), Name("FOO BAR BAZ")), Doc.baptism(Repo.dazho("1-77-1575"), Place.vilnaChurch, None), "", Seq() ), BaptismRecord( "A010", Birth("FOO BAR BAZ", "FOO BAR BAZ", "FOO BAR BAZ", Place.minijky, Date.on("1856-08-21")), Date.on("1856-08-24"), Seq(Name("FOO BAR BAZ"), Name("FOO BAR BAZ")), Doc.baptism(Repo.cdiak("127-1012-3054"), Place.starosilChurch, None), "", Seq() ), BirthCertificate( "A011", Birth("FOO BAR BAZ", "FOO BAR BAZ", "FOO BAR BAZ", Place.shchyh, Date.on("1924-05-17")), Doc.birth(Repo.home, Place.shchyh, None), "", Seq() ), BirthCertificate( "A012", Birth("FOO BAR BAZ", "FOO BAR BAZ", "FOO BAR BAZ", Place.may, Date.on("1931-11-29")), Doc.birth(Repo.home, Place.may, None), "", Seq() ), PersonalDocument("A013", "Колекція документів", Name("FOO"), Doc(Seq("birth", "wedding", "letter"), Repo.home, None, Date.range("1959", "2007")), "todo", Seq()), ) allData.map(i => (i.uid, i.asJson.spaces4)).foreach { t => println(t) }
Write, Run & Share Scala code online using OneCompiler's Scala online compiler for free. It's one of the robust, feature-rich online compilers for Scala language, running on the latest version 2.13.8. Getting started with the OneCompiler's Scala compiler is simple and pretty fast. The editor shows sample boilerplate code when you choose language as Scala
and start coding.
OneCompiler's Scala online editor supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample Scala program which takes name as input and prints hello message with your name.
object Hello {
def main(args: Array[String]): Unit = {
val name = scala.io.StdIn.readLine() // Read input from STDIN
println("Hello " + name )
}
}
Scala is both object-oriented and functional programming language by Martin Odersky in the year 2003.
Variable is a name given to the storage area in order to identify them in our programs.
var or val Variable-name [: Data-Type] = [Initial Value];
If, If-else, Nested-Ifs are used when you want to perform a certain set of operations based on conditional expressions.
if(conditional-expression){
//code
}
if(conditional-expression) {
//code if condition is true
} else {
//code if condition is false
}
if(condition-expression1) {
//code if above condition is true
} else if (condition-expression2) {
//code if above condition is true
}
else if(condition-expression3) {
//code if above condition is true
}
...
else {
//code if all the above conditions are false
}
For loop is used to iterate a set of statements based on a criteria.
for(index <- range){
// code
}
While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.
while(condition) {
// code
}
Do-while is also used to iterate a set of statements based on a condition. It is mostly used when you need to execute the statements atleast once.
do {
// code
} while (condition)
Function is a sub-routine which contains set of statements. Usually functions are written when multiple calls are required to same set of statements which increases re-usuability and modularity.
def functionname(parameters : parameters-type) : returntype = { //code
}
You can either use =
or not in the function definition. If =
is not present, function will not return any value.