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.