trackler 2.0.8.36 → 2.0.8.37
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|