From a6e30cef45f682289a1795faa82dba7e2c259928 Mon Sep 17 00:00:00 2001 From: iKvitka Date: Sun, 18 Oct 2020 01:42:00 +0300 Subject: [PATCH 1/3] Complete Task 1. --- .../task1/src/main/scala/Task1/Task1.scala | 14 ++++++++++++++ .../task1/src/test/scala/Task1/FrequencyTest.scala | 13 +++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task1/src/main/scala/Task1/Task1.scala create mode 100644 Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task1/src/test/scala/Task1/FrequencyTest.scala diff --git a/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task1/src/main/scala/Task1/Task1.scala b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task1/src/main/scala/Task1/Task1.scala new file mode 100644 index 0000000..3f3fb23 --- /dev/null +++ b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task1/src/main/scala/Task1/Task1.scala @@ -0,0 +1,14 @@ +package Task1 + +object Task1 { + /** + * Count the frequency only of english alphabet letters ignoring the case + * + * @param str String that contains different characters + * @return map in which kye is a english alphabet letter and + * value is the appearing frequency of this letter in str string + * if string empty or doesn't contain any letter, you will receive empty map + */ + def getFrequencyOfLetters(str: String): Map[Char, Int] = + str.toCharArray.map(_.toLower).filter(_.isLetter).groupBy(x => x).map(x => (x._1, x._2.size)) +} diff --git a/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task1/src/test/scala/Task1/FrequencyTest.scala b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task1/src/test/scala/Task1/FrequencyTest.scala new file mode 100644 index 0000000..dcb6d19 --- /dev/null +++ b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task1/src/test/scala/Task1/FrequencyTest.scala @@ -0,0 +1,13 @@ +package Task1 + +import org.scalatest._ + +class FrequencyTest extends FlatSpec with Matchers { + it should "Check correctness" in { + Task1.getFrequencyOfLetters("aaaa") should be(Map[Char,Int](('a',4))) + Task1.getFrequencyOfLetters("aaaa1313 _! test") should be(Map[Char,Int](('a',4),('t',2),('e',1),('s',1))) + Task1.getFrequencyOfLetters("") should be(Map[Char,Int]()) + Task1.getFrequencyOfLetters("!!1!??7?") should be(Map[Char,Int]()) + Task1.getFrequencyOfLetters("aaAAaaAA") should be(Map[Char,Int](('a',8))) + } +} From a8ce6e5732daceefc346771b7fbba98af75a24ef Mon Sep 17 00:00:00 2001 From: iKvitka Date: Mon, 19 Oct 2020 01:02:39 +0300 Subject: [PATCH 2/3] Complete Task 2 --- .../task2/src/main/scala/task2/BaseUser.scala | 34 ++++++++++++++ .../task2/src/main/scala/task2/FreeUser.scala | 25 ++++++++++ .../task2/src/main/scala/task2/ProUser.scala | 25 ++++++++++ .../task2/src/test/scala/task2/UserTest.scala | 47 +++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/BaseUser.scala create mode 100644 Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/FreeUser.scala create mode 100644 Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/ProUser.scala create mode 100644 Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/test/scala/task2/UserTest.scala diff --git a/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/BaseUser.scala b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/BaseUser.scala new file mode 100644 index 0000000..11871e9 --- /dev/null +++ b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/BaseUser.scala @@ -0,0 +1,34 @@ +package task2 + +abstract case class BaseUser(username: String, level: Int = 0, experience: Int = 0) { + require("[^a-zA-z0-9._]".r.findFirstIn(username).isEmpty, "username doesn't match. It has to use only [a-z][A-Z][0-9]-._ characters") + + require(level >= 0, "level has to be higher than 0") + + require(experience >= 0, "experience can't be lower than 0") + + val expForLevelUp = 500; + + /** + * add experiance to user for some action + * + * @param amount Int the number of experiance that user will recive for action + * @return User with updated experiance + */ + def addExperience(amount: Int): BaseUser + + /** + * for ProUsers increase payment counter and turns FreeUser to ProUser + * + * @param amount Int the number of days that will be added to payment counter + * @return User with updated payment counter + */ + def pay(amount: Int): BaseUser + + /** + * midnight update will update users level, experiance, action limit and payment counter + * + * @return User with updated state + */ + def midnightUpdate(): BaseUser +} diff --git a/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/FreeUser.scala b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/FreeUser.scala new file mode 100644 index 0000000..ebbc174 --- /dev/null +++ b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/FreeUser.scala @@ -0,0 +1,25 @@ +package task2 + +class FreeUser(username: String, level: Int = 0, experience: Int = 0, val actionLimit: Int = 30) extends BaseUser(username, level, experience) { + override def addExperience(amount: Int): FreeUser = if (actionLimit > 0) new FreeUser(username, level, experience + amount, actionLimit - 1) else this + + override def pay(amount: Int): ProUser = new ProUser(username, level, experience, amount) + + override def midnightUpdate(): FreeUser = { + if (actionLimit < 3) + new FreeUser(username, level + experience / 500, experience % 500, 3) + else + new FreeUser(username, level + experience / 500, experience % 500, actionLimit) + } + + override def canEqual(that: Any): Boolean = that.isInstanceOf[FreeUser] + + override def equals(o: Any): Boolean = o match { + case o: FreeUser => o.canEqual(this) && o.hashCode() == this.hashCode() + case _ => false + } + + override def hashCode(): Int = super.hashCode() + actionLimit.hashCode() + +} + diff --git a/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/ProUser.scala b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/ProUser.scala new file mode 100644 index 0000000..09b1019 --- /dev/null +++ b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/main/scala/task2/ProUser.scala @@ -0,0 +1,25 @@ +package task2 + +class ProUser(username: String, level: Int = 0, experience: Int = 0, paymentCounter: Int = 0) extends BaseUser(username, level, experience) { + override def addExperience(amount: Int): ProUser = new ProUser(username, level, experience + amount, paymentCounter) + + def pay(amount: Int): ProUser = new ProUser(username, level, experience, paymentCounter + amount) + + override def midnightUpdate(): BaseUser = { + if (paymentCounter == 0) { + new FreeUser(username, level + experience / 500, experience % 500) + } else { + new ProUser(username, level + experience / 500, experience % 500, paymentCounter - 1) + } + } + + override def canEqual(that: Any): Boolean = that.isInstanceOf[ProUser] + + override def equals(o: Any): Boolean = o match { + case o: FreeUser => o.canEqual(this) && o.hashCode() == this.hashCode() + case _=> false + } + + override def hashCode(): Int = super.hashCode() + paymentCounter.hashCode() +} + diff --git a/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/test/scala/task2/UserTest.scala b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/test/scala/task2/UserTest.scala new file mode 100644 index 0000000..9515c19 --- /dev/null +++ b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task2/src/test/scala/task2/UserTest.scala @@ -0,0 +1,47 @@ +package task2 + +import org.scalatest._ + +class UserTest extends FlatSpec with Matchers { + it should "throw an IllegalArgumentException for incorrect username" in { + an[IllegalArgumentException] should be thrownBy new FreeUser("nickname check!") + an[IllegalArgumentException] should be thrownBy new ProUser("tester123+4") + } + + it should "throw an IllegalArgumentException for incorrect experience and level" in { + an[IllegalArgumentException] should be thrownBy new FreeUser("nickname", -1) + an[IllegalArgumentException] should be thrownBy new FreeUser("nickname", 0, -1) + } + + it should "update experience to users from add method" in { + val freeUser = new FreeUser("Username", 0, 1, 3) + val proUser = new ProUser("Username", 0, 2, 2) + + freeUser.addExperience(100).equals(new FreeUser("Username", 0, 101, 2)) + proUser.addExperience(100).equals(new ProUser("Username", 0, 102, 2)) + + val noActionUser = new FreeUser("Username", 0, 3, 0) + + noActionUser.addExperience(100).equals(new FreeUser("Username", 0, 3, 0)) + + val zeroExpAdd = new FreeUser("Username", 0, 4, 1) + + zeroExpAdd.addExperience(0).equals((new FreeUser("Username", 0, 4, 0))) + } + + it should "update payment from pay method" in { + val freeUser = new FreeUser("Username", 0, 1, 3) + val proUser = new ProUser("Username", 0, 2, 2) + + freeUser.pay(30).equals(new ProUser("Username", 0, 1, 30)) + proUser.pay(30).equals(new ProUser("Username", 0, 2, 32)) + } + + it should "make correct midnight update" in { + val freeUser = new FreeUser("Username", 1, 1400, 1) + val proUser = new ProUser("Username", 0, 500, 0) + + freeUser.midnightUpdate().equals(new FreeUser("Username", 3, 400, 3)) + proUser.midnightUpdate().equals(new FreeUser("Username", 1, 0, 30)) + } +} From b9a54517ec122c0b59451aafe03e333fb1166f57 Mon Sep 17 00:00:00 2001 From: iKvitka Date: Mon, 19 Oct 2020 03:48:45 +0300 Subject: [PATCH 3/3] Complete Task 3 --- .../task3/src/main/scala/Task3/TSStack.scala | 57 +++++++++++++++++++ .../src/test/scala/Task3/Task3TSStack.scala | 54 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task3/src/main/scala/Task3/TSStack.scala create mode 100644 Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task3/src/test/scala/Task3/Task3TSStack.scala diff --git a/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task3/src/main/scala/Task3/TSStack.scala b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task3/src/main/scala/Task3/TSStack.scala new file mode 100644 index 0000000..265b16f --- /dev/null +++ b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task3/src/main/scala/Task3/TSStack.scala @@ -0,0 +1,57 @@ +package Task3 + +case class TSStack[T](node: List[T] = List()) { + /** + * make stack empty + * + * @return an empty stack + */ + def clear = this.synchronized(TSStack[T]()) + + /** + * check is stack empty + * + * @return true if stack is empty and false if not + */ + def isEmpty = this.synchronized(node.isEmpty) + + /** + * delete the top element of a stack + * + * @return new stack without top element + */ + def pop = this.synchronized { + if (!isEmpty) TSStack[T](node.tail) else TSStack[T]() + } + + /** + * add element to top of stack + * + * @param elem T is an element that will be added to stack + * @return new stack with new top element + */ + def push(elem: T) = this.synchronized { + TSStack(elem :: node) + } + + /** + * get the number of elements in stack + * + * @return number of elements in stack + */ + def size = this.synchronized(node.length) + + /** + * get the top element of stack + * + * @return the top element of stack + */ + def top = this.synchronized(node.headOption) + + /** + * get the string variant of stack + * + * @return string variant of stack + */ + override def toString = this.synchronized(node.toString()) +} diff --git a/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task3/src/test/scala/Task3/Task3TSStack.scala b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task3/src/test/scala/Task3/Task3TSStack.scala new file mode 100644 index 0000000..11262ab --- /dev/null +++ b/Trainee_level_positions/Scala_Software_Engineer/Trainee_Scala_Software_Engineer_Challenge/task3/src/test/scala/Task3/Task3TSStack.scala @@ -0,0 +1,54 @@ +package Task3 + +import org.scalatest._ + +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.{Await, Future} +import scala.concurrent.duration.Duration + +class Task3TSStack extends FlatSpec with Matchers { + + it should "check concurrent push" in { + var pushStack: TSStack[Int] = (TSStack()) + + (1 to 10000).foreach { _ => + var f1 = Future { + pushStack = pushStack.push(1) + } + Await.result(f1, Duration.Inf) + } + + (1 to 10000).foreach { _ => pushStack = pushStack.push(0) } + pushStack.size should be(20000) + } + + it should "Check pop method" in { + var stack: TSStack[Int] = TSStack() + stack = stack.push(0) + stack = stack.push(1) + stack = stack.push(2) + stack = stack.pop + stack should be(new TSStack[Int](List(1, 0))) + stack = stack.pop + stack should be(new TSStack[Int](List(0))) + stack = stack.pop + stack should be(new TSStack[Int](List())) + stack = stack.pop + stack should be(new TSStack[Int](List())) + } + + it should "Check top method" in { + var stack: TSStack[Int] = TSStack() + stack = stack.push(0) + stack = stack.push(1) + stack = stack.push(2) + stack.top should be(Some(2)) + stack = stack.pop + stack.top should be(Some(1)) + stack = stack.pop + stack.top should be(Some(0)) + stack = stack.pop + stack.top should be(None) + + } +}