trackler 2.0.8.36 → 2.0.8.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +7 -0
- data/tracks/c/exercises/perfect-numbers/makefile +16 -0
- data/tracks/c/exercises/perfect-numbers/src/example.c +28 -0
- data/tracks/c/exercises/perfect-numbers/src/example.h +13 -0
- data/tracks/c/exercises/perfect-numbers/src/perfect_numbers.h +11 -0
- data/tracks/c/exercises/perfect-numbers/test/test_perfect_numbers.c +87 -0
- data/tracks/c/exercises/perfect-numbers/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/perfect-numbers/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/perfect-numbers/test/vendor/unity_internals.h +701 -0
- data/tracks/ceylon/README.md +1 -1
- data/tracks/ceylon/docs/RESOURCES.md +5 -0
- data/tracks/ceylon/exercises/anagram/source/anagram/module.ceylon +1 -1
- data/tracks/ceylon/exercises/bracket-push/example/module.ceylon +2 -2
- data/tracks/ceylon/exercises/bracket-push/source/bracketpush/module.ceylon +1 -1
- data/tracks/ceylon/exercises/hamming/source/hamming/module.ceylon +1 -1
- data/tracks/ceylon/exercises/largest-series-product/source/largestseriesproduct/module.ceylon +1 -1
- data/tracks/ceylon/exercises/leap/source/leap/module.ceylon +1 -1
- data/tracks/ceylon/exercises/react/example/module.ceylon +2 -2
- data/tracks/ceylon/exercises/react/source/react/module.ceylon +1 -1
- data/tracks/ceylon/exercises/sieve/example/module.ceylon +2 -2
- data/tracks/ceylon/exercises/sieve/source/sieve/module.ceylon +1 -1
- data/tracks/clojurescript/.github/ISSUE_TEMPLATE.md +9 -0
- data/tracks/clojurescript/.gitignore +4 -0
- data/tracks/clojurescript/.travis.yml +5 -0
- data/tracks/clojurescript/LICENSE +21 -0
- data/tracks/clojurescript/README.md +72 -0
- data/tracks/clojurescript/bin/fetch-configlet +32 -0
- data/tracks/clojurescript/config.json +21 -0
- data/tracks/clojurescript/docs/ABOUT.md +0 -0
- data/tracks/clojurescript/docs/INSTALLATION.md +0 -0
- data/tracks/clojurescript/docs/LEARNING.md +0 -0
- data/tracks/clojurescript/docs/RESOURCES.md +0 -0
- data/tracks/clojurescript/docs/TESTS.md +0 -0
- data/tracks/clojurescript/exercises/TRACK_HINTS.md +0 -0
- data/tracks/clojurescript/img/.keep +0 -0
- data/tracks/csharp/exercises/grade-school/Example.cs +13 -1
- data/tracks/csharp/exercises/grade-school/GradeSchool.cs +1 -1
- data/tracks/csharp/exercises/grade-school/GradeSchoolTest.cs +42 -18
- data/tracks/go/README.md +8 -0
- data/tracks/go/exercises/twelve-days/HINTS.md +2 -0
- data/tracks/haskell/config.json +0 -1
- data/tracks/objective-c/config.json +9 -0
- data/tracks/objective-c/exercises/crypto-square/CryptoSquareExample.h +14 -0
- data/tracks/objective-c/exercises/crypto-square/CryptoSquareExample.m +96 -0
- data/tracks/objective-c/exercises/crypto-square/CryptoSquareTest.m +94 -0
- data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
- data/tracks/purescript/.gitignore +2 -2
- data/tracks/purescript/bin/test-one.sh +58 -0
- data/tracks/purescript/bin/test.sh +13 -44
- data/tracks/purescript/config.json +7 -0
- data/tracks/purescript/exercises/bracket-push/bower.json +17 -0
- data/tracks/purescript/exercises/bracket-push/examples/src/BracketPush.purs +43 -0
- data/tracks/purescript/exercises/bracket-push/src/BracketPush.purs +3 -0
- data/tracks/purescript/exercises/bracket-push/test/Main.purs +64 -0
- data/tracks/scala/exercises/hello-world/HINTS.md +0 -4
- data/tracks/scala/exercises/hello-world/example.scala +1 -2
- data/tracks/scala/exercises/hello-world/src/test/scala/HelloWorldTest.scala +4 -11
- data/tracks/scala/testgen/build.sbt +9 -0
- data/tracks/scala/testgen/project/build.properties +2 -0
- data/tracks/scala/testgen/project/plugins.sbt +2 -0
- data/tracks/scala/testgen/src/main/scala/BeerSongTestGenerator.scala +15 -0
- data/tracks/scala/testgen/src/main/scala/BowlingTestGenerator.scala +23 -44
- data/tracks/scala/testgen/src/main/scala/FoodChainTestGenerator.scala +31 -0
- data/tracks/scala/testgen/src/main/scala/HelloWorldTestGenerator.scala +14 -0
- data/tracks/scala/testgen/src/main/scala/NucleotideCountTestGenerator.scala +15 -0
- data/tracks/scala/testgen/src/main/scala/PangramsTestGenerator.scala +20 -38
- data/tracks/scala/testgen/src/main/scala/SumOfMultiplesTestGenerator.scala +14 -0
- data/tracks/scala/testgen/src/main/scala/testgen/CanonicalDataParser.scala +105 -0
- data/tracks/scala/testgen/src/main/scala/testgen/TestSuiteBuilder.scala +111 -0
- data/tracks/scala/testgen/src/main/twirl/funSuiteTemplate.scala.txt +12 -0
- metadata +44 -4
- data/tracks/haskell/common/stack.yaml +0 -1
- data/tracks/haskell/exercises/pov/.dummylink +0 -1
@@ -0,0 +1,64 @@
|
|
1
|
+
module Test.Main where
|
2
|
+
|
3
|
+
import Prelude
|
4
|
+
import Control.Monad.Eff (Eff)
|
5
|
+
import Test.Unit.Assert as Assert
|
6
|
+
import Test.Unit (suite, test)
|
7
|
+
import Test.Unit.Main (runTest)
|
8
|
+
import BracketPush (isPaired)
|
9
|
+
|
10
|
+
main :: Eff _ Unit
|
11
|
+
main = runTest do
|
12
|
+
suite "BracketPush.isPaired" do
|
13
|
+
|
14
|
+
test "paired square brackets" $
|
15
|
+
Assert.equal true
|
16
|
+
(isPaired "[]")
|
17
|
+
|
18
|
+
test "empty string" $
|
19
|
+
Assert.equal true
|
20
|
+
(isPaired "")
|
21
|
+
|
22
|
+
test "unpaired brackets" $
|
23
|
+
Assert.equal false
|
24
|
+
(isPaired "[[")
|
25
|
+
|
26
|
+
test "wrong ordered brackets" $
|
27
|
+
Assert.equal false
|
28
|
+
(isPaired "}{")
|
29
|
+
|
30
|
+
test "paired with whitespace" $
|
31
|
+
Assert.equal true
|
32
|
+
(isPaired "{ }")
|
33
|
+
|
34
|
+
test "simple nested brackets" $
|
35
|
+
Assert.equal true
|
36
|
+
(isPaired "{[]}")
|
37
|
+
|
38
|
+
test "several paired brackets" $
|
39
|
+
Assert.equal true
|
40
|
+
(isPaired "{}[]")
|
41
|
+
|
42
|
+
test "paired and nested brackets" $
|
43
|
+
Assert.equal true
|
44
|
+
(isPaired "([{}({}[])])")
|
45
|
+
|
46
|
+
test "unopened closing brackets" $
|
47
|
+
Assert.equal false
|
48
|
+
(isPaired "{[)][]}")
|
49
|
+
|
50
|
+
test "unpaired and nested brackets" $
|
51
|
+
Assert.equal false
|
52
|
+
(isPaired "([{])")
|
53
|
+
|
54
|
+
test "paired and wrong nested brackets" $
|
55
|
+
Assert.equal false
|
56
|
+
(isPaired "[({]})")
|
57
|
+
|
58
|
+
test "math expression" $
|
59
|
+
Assert.equal true
|
60
|
+
(isPaired "(((185 + 223.85) * 15) - 543)/2")
|
61
|
+
|
62
|
+
test "complex latex expression" $
|
63
|
+
Assert.equal true
|
64
|
+
(isPaired "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)")
|
@@ -1,8 +1,4 @@
|
|
1
1
|
## Hints
|
2
|
-
For this exercise two Scala features come in handy:
|
3
|
-
- [Default Parameter Values](http://docs.scala-lang.org/tutorials/tour/default-parameter-values.html)
|
4
|
-
- [String Interpolation](http://docs.scala-lang.org/overviews/core/string-interpolation.html)
|
5
2
|
|
6
3
|
#### Common pitfalls that you should avoid
|
7
|
-
- `null` is usually not considered a valid value in Scala, and there are no `null` checks needed (if you don't have to interface with Java code, say). Instead there is the [Option](http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html) type if you want to express the possible absence of a value. But for this exercise just assume a normal non-`null` String parameter.
|
8
4
|
- Usually there is no need in Scala to use `return`. For a discussion see [here](http://stackoverflow.com/questions/24856106/return-in-a-scala-function-literal). Or as a quote from that discussion: *Don't use return, it makes Scala cry.*
|
@@ -1,17 +1,10 @@
|
|
1
1
|
import org.scalatest.{Matchers, FunSuite}
|
2
2
|
|
3
|
+
/** @version 1.0.0 */
|
3
4
|
class HelloWorldTest extends FunSuite with Matchers {
|
4
|
-
test("Without name") {
|
5
|
-
HelloWorld.hello() should be ("Hello, World!")
|
6
|
-
}
|
7
|
-
|
8
|
-
test("with name") {
|
9
|
-
pending
|
10
|
-
HelloWorld.hello("Jane") should be ("Hello, Jane!")
|
11
|
-
}
|
12
5
|
|
13
|
-
test("
|
14
|
-
|
15
|
-
HelloWorld.hello("Jürgen") should be ("Hello, Jürgen!")
|
6
|
+
test("Say Hi!") {
|
7
|
+
HelloWorld.hello() should be ("Hello, World!")
|
16
8
|
}
|
17
9
|
}
|
10
|
+
|
@@ -2,4 +2,13 @@ name := "ExcercismScalaTestGenerator"
|
|
2
2
|
|
3
3
|
scalaVersion := "2.11.8"
|
4
4
|
|
5
|
+
lazy val root = (project in file("."))
|
6
|
+
.enablePlugins(SbtTwirl)
|
7
|
+
.settings(
|
8
|
+
sourceDirectories in (Compile, TwirlKeys.compileTemplates) += (baseDirectory.value.getParentFile / "src" / "main" / "twirl"))
|
9
|
+
|
5
10
|
libraryDependencies += "com.typesafe.play" % "play-json_2.11" % "2.5.3"
|
11
|
+
|
12
|
+
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.4"
|
13
|
+
|
14
|
+
libraryDependencies += "com.typesafe.play" %% "twirl-api" % "1.3.0"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import testgen._
|
2
|
+
import TestSuiteBuilder._
|
3
|
+
import java.io.File
|
4
|
+
|
5
|
+
object BeerSongTestGenerator {
|
6
|
+
def main(args: Array[String]): Unit = {
|
7
|
+
val file = new File("src/main/resources/beer-song.json")
|
8
|
+
|
9
|
+
val code = TestSuiteBuilder.build(file,
|
10
|
+
fromLabeledTestAlt("verse" -> Seq("number"), "verses" -> Seq("beginning", "end")))
|
11
|
+
println(s"-------------")
|
12
|
+
println(code)
|
13
|
+
println(s"-------------")
|
14
|
+
}
|
15
|
+
}
|
@@ -1,49 +1,28 @@
|
|
1
|
-
import
|
2
|
-
|
3
|
-
import
|
4
|
-
|
5
|
-
class BowlingTestGenerator {
|
6
|
-
implicit val testCaseReader = Json.reads[BowlingTestCase]
|
7
|
-
|
8
|
-
private val filename = "bowling.json"
|
9
|
-
private val fileContents = Source.fromFile(filename).getLines.mkString
|
10
|
-
private val json = Json.parse(fileContents)
|
11
|
-
|
12
|
-
def write {
|
13
|
-
val testCases = (json \ "score" \ "cases").get.as[List[BowlingTestCase]]
|
14
|
-
val description = (json \ "score" \ "description").get.as[List[String]].mkString(" ")
|
15
|
-
|
16
|
-
implicit def testCaseToGen(tc: BowlingTestCase): TestCaseGen = {
|
17
|
-
val callSUT =
|
18
|
-
s"${tc.rolls}.foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()"
|
19
|
-
val expected = ""
|
20
|
-
val result = s"val score = $callSUT"
|
21
|
-
val (matchRight, matchLeft) =
|
22
|
-
if (tc.expected == -1)
|
23
|
-
("""fail("Unexpected score returned. Failure expected")""", "")
|
24
|
-
else
|
25
|
-
(s"assert(n == ${tc.expected})", s"""fail("${tc.description}")""")
|
26
|
-
val checkResult =
|
27
|
-
s"""score match {
|
28
|
-
case Right(n) => $matchRight
|
29
|
-
case Left(_) => $matchLeft
|
30
|
-
}"""
|
31
|
-
|
32
|
-
TestCaseGen(tc.description, callSUT, expected, result, checkResult)
|
33
|
-
}
|
34
|
-
|
35
|
-
val testBuilder = new TestBuilder("BowlingTest")
|
36
|
-
testBuilder.addTestCases(testCases, Some(description))
|
37
|
-
testBuilder.toFile
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
|
-
case class BowlingTestCase(description: String,
|
42
|
-
rolls: List[Int],
|
43
|
-
expected: Int)
|
1
|
+
import testgen._
|
2
|
+
import TestSuiteBuilder._
|
3
|
+
import java.io.File
|
44
4
|
|
45
5
|
object BowlingTestGenerator {
|
46
6
|
def main(args: Array[String]): Unit = {
|
47
|
-
new
|
7
|
+
val file = new File("src/main/resources/bowling.json")
|
8
|
+
|
9
|
+
def fromLabeledTest(argNames: String*): ToTestCaseData =
|
10
|
+
withLabeledTest { sut => labeledTest =>
|
11
|
+
val args = sutArgs(labeledTest.result, argNames: _*)
|
12
|
+
val isDefined =
|
13
|
+
labeledTest.expected.fold(Function.const(".isDefined"), Function.const(""))
|
14
|
+
val sutCall =
|
15
|
+
s"""val score = ${args}.foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
16
|
+
score$isDefined"""
|
17
|
+
val expected =
|
18
|
+
labeledTest.expected.fold(Function.const("true"), x => s"Some($x)")
|
19
|
+
|
20
|
+
TestCaseData(labeledTest.description, sutCall, expected)
|
21
|
+
}
|
22
|
+
|
23
|
+
val code = TestSuiteBuilder.build(file, fromLabeledTest("previous_rolls"))
|
24
|
+
println(s"-------------")
|
25
|
+
println(code)
|
26
|
+
println(s"-------------")
|
48
27
|
}
|
49
28
|
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import testgen._
|
2
|
+
import TestSuiteBuilder._
|
3
|
+
import java.io.File
|
4
|
+
|
5
|
+
object FoodChainTestGenerator {
|
6
|
+
def main(args: Array[String]): Unit = {
|
7
|
+
val file = new File("src/main/resources/food-chain.json")
|
8
|
+
|
9
|
+
val RawQuote = "\"\"\""
|
10
|
+
def asRawString(str: String): String = s"$RawQuote$str$RawQuote"
|
11
|
+
|
12
|
+
def fromLabeledTest(argNames: String*)(
|
13
|
+
implicit sutFunction: LabeledTest => String = _.property): ToTestCaseData =
|
14
|
+
withLabeledTest { sut =>
|
15
|
+
labeledTest =>
|
16
|
+
val sutFunction = labeledTest.property
|
17
|
+
val args = sutArgs(labeledTest.result, argNames: _*)
|
18
|
+
val sutCall = s"$sut.$sutFunction(${args})"
|
19
|
+
val expectedLines = labeledTest.expected.right.get.asInstanceOf[List[String]]
|
20
|
+
val expected = expectedLines mkString ("", "\n", "\n\n")
|
21
|
+
|
22
|
+
TestCaseData(labeledTest.description, sutCall, asRawString(expected))
|
23
|
+
}
|
24
|
+
|
25
|
+
val code = TestSuiteBuilder.build(file,
|
26
|
+
fromLabeledTest("start verse"))
|
27
|
+
println(s"-------------")
|
28
|
+
println(code)
|
29
|
+
println(s"-------------")
|
30
|
+
}
|
31
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import testgen._
|
2
|
+
import TestSuiteBuilder._
|
3
|
+
import java.io.File
|
4
|
+
|
5
|
+
object HelloWorldTestGenerator {
|
6
|
+
def main(args: Array[String]): Unit = {
|
7
|
+
val file = new File("src/main/resources/hello-world.json")
|
8
|
+
|
9
|
+
val code = TestSuiteBuilder.build(file, fromLabeledTest())
|
10
|
+
println(s"-------------")
|
11
|
+
println(code)
|
12
|
+
println(s"-------------")
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import testgen._
|
2
|
+
import TestSuiteBuilder._
|
3
|
+
import java.io.File
|
4
|
+
|
5
|
+
object NucleotideCountTestGenerator {
|
6
|
+
|
7
|
+
def main(args: Array[String]): Unit = {
|
8
|
+
val file = new File("src/main/resources/nucleotide-count.json")
|
9
|
+
|
10
|
+
val code = TestSuiteBuilder.build(file, fromLabeledTest("strand"))
|
11
|
+
println(s"-------------")
|
12
|
+
println(code)
|
13
|
+
println(s"-------------")
|
14
|
+
}
|
15
|
+
}
|
@@ -1,43 +1,25 @@
|
|
1
|
-
import
|
2
|
-
|
3
|
-
import
|
4
|
-
|
5
|
-
// Generates test suite from json definition for the Panframs exercise.
|
6
|
-
class PangramsTestGenerator {
|
7
|
-
implicit val pangramTestCaseReader = Json.reads[PangramTestCase]
|
8
|
-
|
9
|
-
private val filename = "pangram.json"
|
10
|
-
private val fileContents = Source.fromFile(filename).getLines.mkString
|
11
|
-
private val json = Json.parse(fileContents)
|
12
|
-
|
13
|
-
def write {
|
14
|
-
print("import org.scalatest.{FunSuite, Matchers}" + System.lineSeparator())
|
15
|
-
print(System.lineSeparator())
|
16
|
-
print("class PangramsTest extends FunSuite with Matchers {" + System.lineSeparator())
|
17
|
-
|
18
|
-
writeTestCases()
|
19
|
-
|
20
|
-
print("}" + System.lineSeparator())
|
21
|
-
}
|
22
|
-
|
23
|
-
private def writeTestCases(): Unit = {
|
24
|
-
val testCases = (json \ "cases").get.as[List[PangramTestCase]]
|
25
|
-
|
26
|
-
testCases.foreach(tc => {
|
27
|
-
print("\ttest(\"" + tc.description + "\") {" + System.lineSeparator())
|
28
|
-
|
29
|
-
println("Pangrams.isPangram(\"" + tc.input + "\") should be (" + tc.expected + ")")
|
30
|
-
|
31
|
-
print("\t}" + System.lineSeparator())
|
32
|
-
print(System.lineSeparator())
|
33
|
-
})
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
case class PangramTestCase(description: String, input: String, expected: Boolean)
|
1
|
+
import testgen._
|
2
|
+
import TestSuiteBuilder._
|
3
|
+
import java.io.File
|
38
4
|
|
39
5
|
object PangramsTestGenerator {
|
40
6
|
def main(args: Array[String]): Unit = {
|
41
|
-
new
|
7
|
+
val file = new File("src/main/resources/pangram.json")
|
8
|
+
def fromLabeledTest(argNames: String*): ToTestCaseData =
|
9
|
+
withLabeledTest { sut =>
|
10
|
+
labeledTest =>
|
11
|
+
val args = sutArgs(labeledTest.result, argNames: _*)
|
12
|
+
val isPangram = labeledTest.property.mkString
|
13
|
+
val sutCall =
|
14
|
+
s"""Pangrams.$isPangram($args)"""
|
15
|
+
val expected =
|
16
|
+
labeledTest.expected.fold(Function.const("true"), x => s"$x")
|
17
|
+
TestCaseData(labeledTest.description, sutCall, expected)
|
18
|
+
}
|
19
|
+
|
20
|
+
val code = TestSuiteBuilder.build(file, fromLabeledTest("input"))
|
21
|
+
println(s"‐‐‐‐‐‐‐‐‐‐‐‐‐")
|
22
|
+
println(code)
|
23
|
+
println(s"‐‐‐‐‐‐‐‐‐‐‐‐‐")
|
42
24
|
}
|
43
25
|
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import testgen._
|
2
|
+
import TestSuiteBuilder._
|
3
|
+
import java.io.File
|
4
|
+
|
5
|
+
object SumOfMultiplesTestGenerator {
|
6
|
+
def main(args: Array[String]): Unit = {
|
7
|
+
val file = new File("src/main/resources/sum-of-multiples.json")
|
8
|
+
|
9
|
+
val code = TestSuiteBuilder.build(file, fromLabeledTest("factors", "limit"))
|
10
|
+
println(s"-------------")
|
11
|
+
println(code)
|
12
|
+
println(s"-------------")
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,105 @@
|
|
1
|
+
package testgen
|
2
|
+
|
3
|
+
import scala.io.Source
|
4
|
+
import scala.util.parsing.json.JSON
|
5
|
+
import CanonicalDataParser._
|
6
|
+
import scala.util.Try
|
7
|
+
import scala.Left
|
8
|
+
import scala.Right
|
9
|
+
import java.io.File
|
10
|
+
|
11
|
+
object CanonicalDataParser {
|
12
|
+
type ParseResult = Map[String,Any]
|
13
|
+
|
14
|
+
type Description = String
|
15
|
+
type Comments = Seq[String]
|
16
|
+
type Cases = Seq[LabeledTestItem]
|
17
|
+
type Property = String
|
18
|
+
type Result = Any
|
19
|
+
type Error = String
|
20
|
+
type Expected = Either[Error, Result]
|
21
|
+
type Properties = Option[Map[String,Any]]
|
22
|
+
|
23
|
+
def getOptional[T](result: ParseResult, key: String): Option[T] =
|
24
|
+
result.get(key).asInstanceOf[Option[T]]
|
25
|
+
def getRequired[T](result: ParseResult, key: String): T =
|
26
|
+
getOptional(result, key) getOrElse (throw new Exception(s"missing: $key"))
|
27
|
+
|
28
|
+
def parse(file: File): Exercise = {
|
29
|
+
val fileContents = Source.fromFile(file).getLines.mkString
|
30
|
+
val rawParseResult =
|
31
|
+
JSON.parseFull(fileContents).get.asInstanceOf[ParseResult]
|
32
|
+
val parseResult = rawParseResult mapValues restoreInts
|
33
|
+
println(parseResult)
|
34
|
+
parseResult
|
35
|
+
}
|
36
|
+
|
37
|
+
private def restoreInts(any: Any): Any =
|
38
|
+
any match {
|
39
|
+
case double: Double if (double.toInt.toDouble == double) => double.toInt
|
40
|
+
case map: Map[_,_] => map mapValues restoreInts
|
41
|
+
case seq: Seq[_] => seq map restoreInts
|
42
|
+
case any => any
|
43
|
+
}
|
44
|
+
|
45
|
+
def main(args: Array[String]): Unit = {
|
46
|
+
val path = "src/main/resources"
|
47
|
+
// val name = "hello-world.json"
|
48
|
+
// val name = "sum-of-multiples.json"
|
49
|
+
val name = "bowling.json"
|
50
|
+
val result = parse(new File(s"$path/$name"))
|
51
|
+
println(result)
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
case class Exercise(name: String, version: String, cases: Cases,
|
56
|
+
comments: Option[Comments])
|
57
|
+
object Exercise {
|
58
|
+
implicit def fromParseResult(result: ParseResult): Exercise = {
|
59
|
+
val cases: Cases =
|
60
|
+
getRequired[Seq[ParseResult]](result, "cases") map LabeledTestItem.fromParseResult
|
61
|
+
Exercise(getRequired(result, "exercise"), getRequired(result, "version"),
|
62
|
+
flattenCases(cases), getOptional(result, "comments"))
|
63
|
+
}
|
64
|
+
|
65
|
+
// so far there are to few LabeledTestGroups to handle them separately
|
66
|
+
private def flattenCases(cases: Cases): Cases =
|
67
|
+
cases match {
|
68
|
+
case Seq() => Seq()
|
69
|
+
case (ltg: LabeledTestGroup) +: xs => ltg.cases ++ flattenCases(xs)
|
70
|
+
case (lt: LabeledTest) +: xs => lt +: flattenCases(xs)
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
sealed trait LabeledTestItem
|
75
|
+
object LabeledTestItem {
|
76
|
+
implicit def fromParseResult(result: ParseResult): LabeledTestItem =
|
77
|
+
if (result.contains("cases")) result: LabeledTestGroup
|
78
|
+
else result: LabeledTest
|
79
|
+
}
|
80
|
+
|
81
|
+
case class LabeledTest(description: Description, property: Property,
|
82
|
+
expected: Expected, result: ParseResult) extends LabeledTestItem
|
83
|
+
object LabeledTest {
|
84
|
+
implicit def fromParseResult(result: ParseResult): LabeledTest = {
|
85
|
+
val expected: Expected = {
|
86
|
+
val any = getRequired[Any](result, "expected")
|
87
|
+
val error = Try {
|
88
|
+
Left(any.asInstanceOf[Map[String,String]]("error"))
|
89
|
+
}
|
90
|
+
error.getOrElse(Right(any))
|
91
|
+
}
|
92
|
+
LabeledTest(getRequired(result, "description"), getRequired(result, "property"),
|
93
|
+
expected, result)
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
case class LabeledTestGroup(description: Description, cases: Cases) extends LabeledTestItem
|
98
|
+
object LabeledTestGroup {
|
99
|
+
implicit def fromParseResult(result: ParseResult): LabeledTestGroup = {
|
100
|
+
val description = getRequired[String](result, "description")
|
101
|
+
val cases =
|
102
|
+
getRequired[Seq[ParseResult]](result, "cases") map LabeledTestItem.fromParseResult
|
103
|
+
LabeledTestGroup(description, cases)
|
104
|
+
}
|
105
|
+
}
|