trackler 2.1.0.26 → 2.1.0.27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/common/CONTRIBUTING.md +0 -15
  3. data/common/exercises/secret-handshake/canonical-data.json +14 -7
  4. data/lib/trackler/version.rb +1 -1
  5. data/tracks/dlang/config.json +18 -0
  6. data/tracks/dlang/exercises/leap/leap.d +8 -0
  7. data/tracks/dlang/exercises/leap/leap_example.d +15 -0
  8. data/tracks/dlang/exercises/react/react.d +211 -0
  9. data/tracks/dlang/exercises/react/react_example.d +291 -0
  10. data/tracks/factor/README.md +7 -7
  11. data/tracks/factor/config.json +13 -4
  12. data/tracks/factor/exercises/hello-world/hello-world-example.factor +2 -3
  13. data/tracks/factor/exercises/hello-world/hello-world-tests.factor +1 -5
  14. data/tracks/factor/exercises/hello-world/hello-world.factor +1 -1
  15. data/tracks/factor/exercises/two-fer/two-fer-example.factor +6 -0
  16. data/tracks/factor/exercises/two-fer/two-fer-tests.factor +8 -0
  17. data/tracks/fortran/Makefile +1 -2
  18. data/tracks/fortran/config.json +6 -0
  19. data/tracks/fortran/exercises/bob/bob.fun +18 -18
  20. data/tracks/fortran/exercises/hamming/example.f90 +25 -0
  21. data/tracks/fortran/exercises/hamming/hamming.fun +75 -0
  22. data/tracks/go/exercises/poker/.meta/gen.go +76 -0
  23. data/tracks/go/exercises/poker/cases_test.go +240 -0
  24. data/tracks/go/exercises/poker/example.go +10 -1
  25. data/tracks/go/exercises/poker/poker_test.go +1 -224
  26. data/tracks/go/exercises/sum-of-multiples/.meta/gen.go +43 -0
  27. data/tracks/go/exercises/sum-of-multiples/cases_test.go +24 -0
  28. data/tracks/go/exercises/sum-of-multiples/example.go +1 -1
  29. data/tracks/go/exercises/sum-of-multiples/sum_of_multiples_test.go +1 -18
  30. data/tracks/groovy/exercises/robot-name/RobotSpec.groovy +38 -0
  31. data/tracks/kotlin/config.json +10 -0
  32. data/tracks/kotlin/exercises/collatz-conjecture/build.gradle +28 -0
  33. data/tracks/kotlin/exercises/collatz-conjecture/src/example/kotlin/CollatzCalculator.kt +12 -0
  34. data/tracks/kotlin/exercises/collatz-conjecture/src/main/kotlin/.keep +0 -0
  35. data/tracks/kotlin/exercises/collatz-conjecture/src/test/kotlin/CollatzCalculatorTest.kt +51 -0
  36. data/tracks/kotlin/exercises/diamond/build.gradle +28 -0
  37. data/tracks/kotlin/exercises/diamond/src/example/kotlin/DiamondPrinter.kt +35 -0
  38. data/tracks/kotlin/exercises/diamond/src/main/kotlin/DiamondPrinter.kt +5 -0
  39. data/tracks/kotlin/exercises/diamond/src/test/kotlin/DiamondPrinterTest.kt +121 -0
  40. data/tracks/kotlin/exercises/settings.gradle +2 -0
  41. data/tracks/ocaml/.gitignore +1 -0
  42. data/tracks/ocaml/.vscode/launch.json +14 -0
  43. data/tracks/ocaml/tools/test-generator/src/controller.ml +15 -16
  44. data/tracks/ocaml/tools/test-generator/src/languages.ml +30 -0
  45. data/tracks/ocaml/tools/test-generator/src/ocaml_special_cases.ml +137 -0
  46. data/tracks/ocaml/tools/test-generator/src/purescript_special_cases.ml +13 -0
  47. data/tracks/ocaml/tools/test-generator/src/special_cases.ml +7 -132
  48. data/tracks/ocaml/tools/test-generator/src/template.ml +3 -3
  49. data/tracks/ocaml/tools/test-generator/src/test_gen.ml +13 -3
  50. data/tracks/ocaml/tools/test-generator/templates/{acronym → ocaml/acronym}/template.ml +0 -0
  51. data/tracks/ocaml/tools/test-generator/templates/{all-your-base → ocaml/all-your-base}/template.ml +0 -0
  52. data/tracks/ocaml/tools/test-generator/templates/{anagram → ocaml/anagram}/template.ml +0 -0
  53. data/tracks/ocaml/tools/test-generator/templates/{atbash-cipher → ocaml/atbash-cipher}/template.ml +0 -0
  54. data/tracks/ocaml/tools/test-generator/templates/{beer-song → ocaml/beer-song}/template.ml +0 -0
  55. data/tracks/ocaml/tools/test-generator/templates/{binary-search → ocaml/binary-search}/template.ml +0 -0
  56. data/tracks/ocaml/tools/test-generator/templates/{bob → ocaml/bob}/template.ml +0 -0
  57. data/tracks/ocaml/tools/test-generator/templates/{bowling → ocaml/bowling}/template.ml +0 -0
  58. data/tracks/ocaml/tools/test-generator/templates/{bracket-push → ocaml/bracket-push}/template.ml +0 -0
  59. data/tracks/ocaml/tools/test-generator/templates/{change → ocaml/change}/template.ml +0 -0
  60. data/tracks/ocaml/tools/test-generator/templates/{connect → ocaml/connect}/template.ml +0 -0
  61. data/tracks/ocaml/tools/test-generator/templates/{difference-of-squares → ocaml/difference-of-squares}/template.ml +0 -0
  62. data/tracks/ocaml/tools/test-generator/templates/{dominoes → ocaml/dominoes}/template.ml +0 -0
  63. data/tracks/ocaml/tools/test-generator/templates/{etl → ocaml/etl}/template.ml +0 -0
  64. data/tracks/ocaml/tools/test-generator/templates/{forth → ocaml/forth}/template.ml +0 -0
  65. data/tracks/ocaml/tools/test-generator/templates/{hamming → ocaml/hamming}/template.ml +0 -0
  66. data/tracks/ocaml/tools/test-generator/templates/{hello-world → ocaml/hello-world}/template.ml +0 -0
  67. data/tracks/ocaml/tools/test-generator/templates/{leap → ocaml/leap}/template.ml +0 -0
  68. data/tracks/ocaml/tools/test-generator/templates/{luhn → ocaml/luhn}/template.ml +0 -0
  69. data/tracks/ocaml/tools/test-generator/templates/{minesweeper → ocaml/minesweeper}/template.ml +0 -0
  70. data/tracks/ocaml/tools/test-generator/templates/{pangram → ocaml/pangram}/template.ml +0 -0
  71. data/tracks/ocaml/tools/test-generator/templates/{phone-number → ocaml/phone-number}/template.ml +0 -0
  72. data/tracks/ocaml/tools/test-generator/templates/{prime-factors → ocaml/prime-factors}/template.ml +0 -0
  73. data/tracks/ocaml/tools/test-generator/templates/{raindrops → ocaml/raindrops}/template.ml +0 -0
  74. data/tracks/ocaml/tools/test-generator/templates/{roman-numerals → ocaml/roman-numerals}/template.ml +0 -0
  75. data/tracks/ocaml/tools/test-generator/templates/{run-length-encoding → ocaml/run-length-encoding}/template.ml +0 -0
  76. data/tracks/ocaml/tools/test-generator/templates/{say → ocaml/say}/template.ml +0 -0
  77. data/tracks/ocaml/tools/test-generator/templates/{space-age → ocaml/space-age}/template.ml +0 -0
  78. data/tracks/ocaml/tools/test-generator/templates/{triangle → ocaml/triangle}/template.ml +0 -0
  79. data/tracks/ocaml/tools/test-generator/templates/{word-count → ocaml/word-count}/template.ml +0 -0
  80. data/tracks/ocaml/tools/test-generator/templates/purescript/hamming/Main.purs +18 -0
  81. data/tracks/ocaml/tools/test-generator/test/all_tests.ml +2 -2
  82. data/tracks/ocaml/tools/test-generator/test/{special_cases_test.ml → ocaml_special_cases_test.ml} +3 -3
  83. data/tracks/ocaml/tools/test-generator/test/template_test.ml +1 -0
  84. metadata +59 -34
  85. data/tracks/groovy/exercises/robot-name/RobotTest.groovy +0 -34
@@ -0,0 +1,12 @@
1
+ object CollatzCalculator {
2
+
3
+ fun computeStepCount(start: Int): Int {
4
+ require(start > 0) { "Only natural numbers are allowed" }
5
+
6
+ if (start == 1) return 0
7
+
8
+ val next = if (start % 2 == 0) start / 2 else 3 * start + 1
9
+ return 1 + computeStepCount(next)
10
+ }
11
+
12
+ }
@@ -0,0 +1,51 @@
1
+ import org.junit.Ignore
2
+ import org.junit.Rule
3
+ import org.junit.Test
4
+ import org.junit.rules.ExpectedException
5
+ import kotlin.test.assertEquals
6
+
7
+ /*
8
+ * version: 1.0.0
9
+ */
10
+ class CollatzCalculatorTest {
11
+
12
+ @Rule
13
+ @JvmField
14
+ var expectedException: ExpectedException = ExpectedException.none()
15
+
16
+ @Test
17
+ fun testZeroStepsRequiredWhenStartingFrom1() {
18
+ assertEquals(0, CollatzCalculator.computeStepCount(1))
19
+ }
20
+
21
+ @Ignore
22
+ @Test
23
+ fun testCorrectNumberOfStepsWhenAllStepsAreDivisions() {
24
+ assertEquals(4, CollatzCalculator.computeStepCount(16))
25
+ }
26
+
27
+ @Ignore
28
+ @Test
29
+ fun testCorrectNumberOfStepsWhenBothStepTypesAreNeeded() {
30
+ assertEquals(9, CollatzCalculator.computeStepCount(12))
31
+ }
32
+
33
+ @Ignore
34
+ @Test
35
+ fun testZeroIsConsideredInvalidInput() {
36
+ expectedException.expect(IllegalArgumentException::class.java)
37
+ expectedException.expectMessage("Only natural numbers are allowed")
38
+
39
+ CollatzCalculator.computeStepCount(0)
40
+ }
41
+
42
+ @Ignore
43
+ @Test
44
+ fun testNegativeIntegerIsConsideredInvalidInput() {
45
+ expectedException.expect(IllegalArgumentException::class.java)
46
+ expectedException.expectMessage("Only natural numbers are allowed")
47
+
48
+ CollatzCalculator.computeStepCount(-15)
49
+ }
50
+
51
+ }
@@ -0,0 +1,28 @@
1
+ buildscript {
2
+ ext.kotlin_version = '1.1.1'
3
+ repositories {
4
+ mavenCentral()
5
+ }
6
+ dependencies {
7
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
8
+ }
9
+ }
10
+
11
+ apply plugin: 'kotlin'
12
+
13
+ repositories {
14
+ mavenCentral()
15
+ }
16
+
17
+ dependencies {
18
+ compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
19
+
20
+ testCompile 'junit:junit:4.12'
21
+ testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
22
+ }
23
+ test {
24
+ testLogging {
25
+ exceptionFormat = 'full'
26
+ events = ["passed", "failed", "skipped"]
27
+ }
28
+ }
@@ -0,0 +1,35 @@
1
+ import java.util.*
2
+
3
+ class DiamondPrinter {
4
+
5
+ companion object {
6
+ private val A_INT = 'A'.toInt()
7
+
8
+ private fun blank(length: Int): String {
9
+ return Collections.nCopies(length, " ").joinToString("")
10
+ }
11
+ }
12
+
13
+ fun printToList(chr: Char): List<String> {
14
+ val nRows = 2 * (chr.toInt() - A_INT) + 1
15
+
16
+ val result = mutableListOf<String>()
17
+
18
+ // Populate the top rows.
19
+ for (nRow in 0..(nRows + 1) / 2 - 1) {
20
+ val rowChr = (A_INT + nRow).toChar()
21
+
22
+ val leftHalfOfRow = blank((nRows - 1) / 2 - nRow) + rowChr + blank(nRow)
23
+ val rightHalfOfRow = leftHalfOfRow.reversed().drop(1)
24
+ val fullRow = "$leftHalfOfRow$rightHalfOfRow"
25
+
26
+ result.add(fullRow)
27
+ }
28
+
29
+ // Populate the bottom rows by 'reflecting' all rows above the middle row.
30
+ result.addAll(result.reversed().drop(1))
31
+
32
+ return result
33
+ }
34
+
35
+ }
@@ -0,0 +1,5 @@
1
+ class DiamondPrinter {
2
+
3
+
4
+
5
+ }
@@ -0,0 +1,121 @@
1
+ import org.hamcrest.CoreMatchers.`is`
2
+ import org.junit.Assert.assertThat
3
+ import org.junit.Before
4
+ import org.junit.Ignore
5
+ import org.junit.Test
6
+
7
+ /*
8
+ * version: 1.0.0
9
+ */
10
+ class DiamondPrinterTest {
11
+
12
+ private lateinit var diamondPrinter: DiamondPrinter
13
+
14
+ @Before
15
+ fun setUp() {
16
+ diamondPrinter = DiamondPrinter()
17
+ }
18
+
19
+ @Test
20
+ fun testOneByOneDiamond() {
21
+ val output = diamondPrinter.printToList('A')
22
+ assertThat(output, `is`(listOf("A")))
23
+ }
24
+
25
+ @Ignore
26
+ @Test
27
+ fun testTwoByTwoDiamond() {
28
+ val output = diamondPrinter.printToList('B')
29
+ assertThat(output, `is`(listOf(
30
+ " A ",
31
+ "B B",
32
+ " A ")))
33
+ }
34
+
35
+ @Ignore
36
+ @Test
37
+ fun testThreeByThreeDiamond() {
38
+ val output = diamondPrinter.printToList('C')
39
+ assertThat(output, `is`(listOf(
40
+ " A ",
41
+ " B B ",
42
+ "C C",
43
+ " B B ",
44
+ " A ")))
45
+ }
46
+
47
+ @Ignore
48
+ @Test
49
+ fun testFiveByFiveDiamond() {
50
+ val output = diamondPrinter.printToList('E')
51
+ assertThat(output, `is`(listOf(
52
+ " A ",
53
+ " B B ",
54
+ " C C ",
55
+ " D D ",
56
+ "E E",
57
+ " D D ",
58
+ " C C ",
59
+ " B B ",
60
+ " A ")))
61
+ }
62
+
63
+ @Ignore
64
+ @Test
65
+ fun testFullDiamond() {
66
+ val output = diamondPrinter.printToList('Z')
67
+ assertThat(output, `is`(listOf(
68
+ " A ",
69
+ " B B ",
70
+ " C C ",
71
+ " D D ",
72
+ " E E ",
73
+ " F F ",
74
+ " G G ",
75
+ " H H ",
76
+ " I I ",
77
+ " J J ",
78
+ " K K ",
79
+ " L L ",
80
+ " M M ",
81
+ " N N ",
82
+ " O O ",
83
+ " P P ",
84
+ " Q Q ",
85
+ " R R ",
86
+ " S S ",
87
+ " T T ",
88
+ " U U ",
89
+ " V V ",
90
+ " W W ",
91
+ " X X ",
92
+ " Y Y ",
93
+ "Z Z",
94
+ " Y Y ",
95
+ " X X ",
96
+ " W W ",
97
+ " V V ",
98
+ " U U ",
99
+ " T T ",
100
+ " S S ",
101
+ " R R ",
102
+ " Q Q ",
103
+ " P P ",
104
+ " O O ",
105
+ " N N ",
106
+ " M M ",
107
+ " L L ",
108
+ " K K ",
109
+ " J J ",
110
+ " I I ",
111
+ " H H ",
112
+ " G G ",
113
+ " F F ",
114
+ " E E ",
115
+ " D D ",
116
+ " C C ",
117
+ " B B ",
118
+ " A ")))
119
+ }
120
+
121
+ }
@@ -46,3 +46,5 @@ include 'binary-search'
46
46
  include 'triangle'
47
47
  include 'bank-account'
48
48
  include 'sum-of-multiples'
49
+ include 'diamond'
50
+ include 'collatz-conjecture'
@@ -7,3 +7,4 @@ tmp
7
7
  _build/
8
8
  bin/configlet
9
9
  bin/configlet.exe
10
+ .psc-ide-port
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "OCaml",
6
+ "type": "ocamldebug",
7
+ "request": "launch",
8
+ "program": "${workspaceRoot}/tools/test-generator/test_gen.byte",
9
+ "console": "internalConsole",
10
+ "stopOnEntry": false,
11
+ "args": ["-l", "purescript" ,"-o", "/home/steve/dev/exercism/xpurescript/exercises"]
12
+ }
13
+ ]
14
+ }
@@ -6,6 +6,7 @@ open Codegen
6
6
  open Special_cases
7
7
  open Template
8
8
  open Files
9
+ open Languages
9
10
 
10
11
  type content = string
11
12
 
@@ -15,8 +16,8 @@ let find_nested_files (name: string) (base: string): (string * content) list =
15
16
  |> List.filter ~f:(fun slug -> Sys.file_exists_exn (base ^ "/" ^ slug ^ "/" ^ name))
16
17
  |> List.map ~f:(fun slug -> (slug, In_channel.read_all (base ^ "/" ^ slug ^ "/" ^ name)))
17
18
 
18
- let find_template_files base filter =
19
- let all_files = find_nested_files "template.ml" base in
19
+ let find_template_files base filter template_filename =
20
+ let all_files = find_nested_files template_filename base in
20
21
  let filter = Option.value filter ~default:"" in
21
22
  List.filter all_files ~f:(fun (slug,_) -> String.is_substring slug ~substring:filter)
22
23
 
@@ -32,18 +33,19 @@ let simplify_single_test_suite (canonical_data: canonical_data): canonical_data
32
33
  | _ -> canonical_data
33
34
 
34
35
 
35
- let prepend_version (v: string option) (str: string): string = match v with
36
+ let prepend_version (version_printer: string -> string) (v: string option) (str: string): string = match v with
36
37
  | None -> str
37
- | Some v -> "(* Test/exercise version: \"" ^ v ^ "\" *)\n\n" ^ str
38
+ | Some v -> (version_printer v) ^ str
38
39
 
39
- let generate_code ~(slug: string) ~(template_file: content) ~(canonical_data_file: content): (content, string) Result.t =
40
+ let generate_code ~(lc: language_config) ~(slug: string) ~(template_file: content) ~(canonical_data_file: content): (content, string) Result.t =
40
41
  let open Result.Monad_infix in
41
- Result.of_option ~error:("cannot recognize file for " ^ slug ^ " as a template") @@ find_template template_file >>= fun template ->
42
- let edit_expected = edit_expected ~stringify:json_to_string ~slug in
42
+ Result.of_option ~error:("cannot recognize file for " ^ slug ^ " as a template") @@ find_template template_file lc.test_start_marker lc.test_end_marker >>= fun template ->
43
+ let edit_expected = edit_expected ~language:lc.name ~stringify:json_to_string ~slug in
43
44
  let edit_parameters = edit_parameters ~slug in
44
45
  let fill_in_template = fill_in_template edit_expected edit_parameters in
45
46
  let file_text = template.file_text in
46
47
  let file_lines = String.split_lines file_text |> List.to_array in
48
+ let prepend_version = prepend_version lc.version_printer in
47
49
  parse_json_text canonical_data_file (expected_key_name slug) (cases_name slug)
48
50
  |> Result.map_error ~f:show_error >>| simplify_single_test_suite >>= fun cd -> (match cd.tests with
49
51
  | Single cases ->
@@ -65,10 +67,10 @@ let generate_code ~(slug: string) ~(template_file: content) ~(canonical_data_fil
65
67
  |> Result.map ~f:(prepend_version cd.version)
66
68
  )
67
69
 
68
- let output_tests (files: (string * content * content) list) (output_folder: string) ~(generated_folder: string): unit =
69
- let output_filepath name = output_folder ^ "/" ^ name ^ "/test.ml" in
70
+ let output_tests (lc: language_config) (files: (string * content * content) list) (output_folder: string) ~(generated_folder: string): unit =
71
+ let output_filepath name = output_folder ^ "/" ^ name ^ "/" ^ lc.template_file_name in
70
72
  let output1 (slug,t,c) =
71
- match generate_code slug t c with
73
+ match generate_code lc slug t c with
72
74
  | Ok code ->
73
75
  if backup ~base_folder:generated_folder ~slug ~contents:code
74
76
  then Out_channel.write_all (output_filepath slug) code
@@ -76,14 +78,11 @@ let output_tests (files: (string * content * content) list) (output_folder: stri
76
78
  | Error e -> print_endline ("Failed when generating " ^ slug ^ ", error: " ^ e) in
77
79
  List.iter files ~f:output1
78
80
 
79
- (*let add_header (canonical_data_folder: string) (generated: string): string =*)
80
-
81
-
82
- let run ~(templates_folder: string) ~(canonical_data_folder: string) ~(output_folder: string) ~(generated_folder: string) (filter: string option) =
83
- let template_files = find_template_files templates_folder filter in
81
+ let run ~(language_config: language_config) ~(templates_folder: string) ~(canonical_data_folder: string) ~(output_folder: string) ~(generated_folder: string) (filter: string option) =
82
+ let template_files = find_template_files templates_folder filter language_config.template_file_name in
84
83
  let canonical_data_files = find_canonical_data_files canonical_data_folder in
85
84
  let combined = combine_files template_files canonical_data_files in
86
- output_tests combined output_folder generated_folder
85
+ output_tests language_config combined output_folder generated_folder
87
86
 
88
87
  let check_canonical_data canonical_data_folder =
89
88
  let ok_count = ref 0 in
@@ -0,0 +1,30 @@
1
+ open Core
2
+
3
+ type language_config = {
4
+ name: string;
5
+ template_file_name: string;
6
+ default_base_folder: string;
7
+ test_start_marker: string;
8
+ test_end_marker: string;
9
+ version_printer: string -> string
10
+ }
11
+
12
+ let default_language_config = function
13
+ | "ocaml" -> {
14
+ name = "ocaml";
15
+ template_file_name = "template.ml";
16
+ default_base_folder = "../..";
17
+ test_start_marker = "(* TEST";
18
+ test_end_marker = "END TEST";
19
+ version_printer = fun v -> "(* Test/exercise version: \"" ^ v ^ "\" *)\n\n";
20
+ }
21
+ | "purescript" -> {
22
+ name = "purescript";
23
+ template_file_name = "Main.purs";
24
+ default_base_folder = "../../../xpurescript";
25
+ test_start_marker = "--TEST";
26
+ test_end_marker = "--END TEST";
27
+ version_printer = fun v -> "-- Test/exercise version: \"" ^ v ^ "\"\n\n";
28
+ }
29
+ | x -> failwith @@ "unknown language " ^ x
30
+
@@ -0,0 +1,137 @@
1
+ open Core
2
+
3
+ open Model
4
+ open Yojson.Basic
5
+
6
+ let strip_quotes s = String.drop_prefix s 1 |> Fn.flip String.drop_suffix 1
7
+
8
+ let map_elements (to_str: json -> string) (parameters: (string * json) list): (string * string) list =
9
+ List.map parameters ~f:(fun (k,j) -> (k,to_str j))
10
+
11
+ let optional_int ~(none: int) = function
12
+ | `Int n when n = none -> "None"
13
+ | `Int n -> "(Some " ^ Int.to_string n ^ ")"
14
+ | x -> json_to_string x
15
+
16
+ let optional_int_list = function
17
+ | `List xs -> "(Some [" ^ String.concat ~sep:"; " (List.map ~f:json_to_string xs) ^ "])"
18
+ | _ -> "None"
19
+
20
+ let optional_int_or_string ~(none: int) = function
21
+ | `String s -> "(Some \"" ^ s ^ "\")"
22
+ | `Int n when n = none -> "None"
23
+ | x -> json_to_string x
24
+
25
+ let default_value ~(key: string) ~(value: string) (parameters: (string * string) list): (string * string) list =
26
+ if List.exists ~f:(fun (k, _) -> k = key) parameters
27
+ then parameters
28
+ else (key, value) :: parameters
29
+
30
+ let optional_strings ~(f: string -> bool) (parameters: (string * json) list): (string * string) list =
31
+ let replace parameter =
32
+ let (k, v) = parameter in
33
+ if f k
34
+ then (k, "(Some " ^ json_to_string v ^ ")")
35
+ else (k, json_to_string v) in
36
+ List.map ~f:replace parameters
37
+
38
+ let option_of_null (value: json): string = match value with
39
+ | `Null -> "None"
40
+ | `String s -> "(Some \"" ^ s ^ "\")"
41
+ | `List xs as l -> "(Some " ^ (json_to_string l) ^ ")"
42
+ | _ -> failwith "cannot handle this type"
43
+
44
+ let is_empty_string (value: json): bool = match value with
45
+ | `String s -> String.is_empty s
46
+ | _ -> false
47
+
48
+ let edit_connect_expected = function
49
+ | `String "X" -> "(Some X)"
50
+ | `String "O" -> "(Some O)"
51
+ | `String "" -> "None"
52
+ | x -> failwith "Bad json value in connect " ^ json_to_string x
53
+
54
+ let edit_change_expected (value: json) = match value with
55
+ | `List xs -> "(Some [" ^ (String.concat ~sep:"; " (List.map ~f:json_to_string xs)) ^ "])"
56
+ | `Int (-1) -> "None"
57
+ | _ -> failwith "Bad json value in change"
58
+
59
+ let edit_bowling_expected (value: json) = match value with
60
+ | `Int n -> "(Ok " ^ (Int.to_string n) ^ ")"
61
+ | `Assoc [(k, v)] ->
62
+ if k = "error" then "(Error " ^ json_to_string v ^ ")" else failwith ("Can only handle error value but got " ^ k)
63
+ | _ -> failwith "Bad json value in bowling"
64
+
65
+ let ocaml_edit_expected ~(stringify: json -> string) ~(slug: string) ~(value: json) = match slug with
66
+ | "hamming" -> optional_int ~none:(-1) value
67
+ | "all-your-base" -> optional_int_list value
68
+ | "say" -> optional_int_or_string ~none:(-1) value
69
+ | "phone-number" -> option_of_null value
70
+ | "connect" -> edit_connect_expected value
71
+ | "change" -> edit_change_expected value
72
+ | "bowling" -> edit_bowling_expected value
73
+ | "binary-search" -> optional_int ~none:(-1) value
74
+ | "forth" -> option_of_null value
75
+ | _ -> stringify value
76
+
77
+ let edit_say (ps: (string * json) list) =
78
+ let edit = function
79
+ | ("input", v) -> ("input", let v = json_to_string v in if Int.of_string v >= 0 then "(" ^ v ^ "L)" else v ^ "L")
80
+ | (k, ps) -> (k, json_to_string ps) in
81
+ List.map ps ~f:edit
82
+
83
+ let edit_all_your_base (ps: (string * json) list): (string * string) list =
84
+ let edit = function
85
+ | ("output_base", v) -> let v = json_to_string v in ("output_base", if Int.of_string v >= 0 then v else "(" ^ v ^ ")")
86
+ | ("input_base", v) -> let v = json_to_string v in ("input_base", if Int.of_string v >= 0 then v else "(" ^ v ^ ")")
87
+ | (k, v) -> (k, json_to_string v) in
88
+ List.map ps ~f:edit
89
+
90
+ let edit_dominoes (ps: (string * json) list): (string * string) list =
91
+ let two_elt_list_to_tuple (j: json): string = match j with
92
+ | `List [`Int x1; `Int x2] -> sprintf "(%d,%d)" x1 x2
93
+ | _ -> failwith "two element list expected, but got " ^ (json_to_string j) in
94
+ let edit (p: (string * json)) = match p with
95
+ | ("input", `List j) -> ("input", "[" ^ (List.map ~f:two_elt_list_to_tuple j |> String.concat ~sep:"; ") ^ "]")
96
+ | (k, v) -> (k, json_to_string v) in
97
+ List.map ps ~f:edit
98
+
99
+
100
+ let edit_space_age (ps: (string * json) list): (string * string) list =
101
+ let edit = function
102
+ | ("planet", v) -> ("planet", json_to_string v |> strip_quotes)
103
+ | (k, v) -> (k, json_to_string v) in
104
+ List.map ps ~f:edit
105
+
106
+ let edit_bowling (ps: (string * json) list): (string * string) list =
107
+ let edit = function
108
+ | ("property", v) -> ("property", json_to_string v |> strip_quotes)
109
+ | ("roll", `Int n) -> ("roll", let s = Int.to_string n in if n < 0 then ("(" ^ s ^ ")") else s)
110
+ | (k, v) -> (k, json_to_string v) in
111
+ List.map ps ~f:edit
112
+
113
+ let edit_binary_search (ps: (string * json) list): (string * string) list =
114
+ let open Yojson.Basic.Util in
115
+ let as_array_string xs =
116
+ let xs = to_list xs |> List.map ~f:to_int |> List.map ~f:Int.to_string in
117
+ "[|" ^ String.concat ~sep:"; " xs ^ "|]" in
118
+ let edit = function
119
+ | ("array", v) -> ("array", as_array_string v)
120
+ | (k, v) -> (k, json_to_string v) in
121
+ List.map ps ~f:edit
122
+
123
+ let edit_parameters ~(slug: string) (parameters: (string * json) list) = match (slug, parameters) with
124
+ | ("hello-world", ps) -> default_value ~key:"name" ~value:"None" (optional_strings ~f:(fun _x -> true) parameters)
125
+ | ("say", ps) -> edit_say ps
126
+ | ("all-your-base", ps) -> edit_all_your_base ps
127
+ | ("dominoes", ps) -> edit_dominoes ps
128
+ | ("space-age", ps) -> edit_space_age ps
129
+ | ("bowling", ps) -> edit_bowling ps
130
+ | ("binary-search", ps) -> edit_binary_search ps
131
+ | (_, ps) -> map_elements json_to_string ps
132
+
133
+ let expected_key_name slug = match slug with
134
+ | "dominoes" -> "can_chain"
135
+ | _ -> "expected"
136
+
137
+ let cases_name _slug = "cases"