trackler 2.2.1.40 → 2.2.1.41

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.
Files changed (376) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/lib/trackler/version.rb +1 -1
  4. data/problem-specifications/exercises/dot-dsl/metadata.yml +1 -0
  5. data/problem-specifications/exercises/etl/metadata.yml +1 -0
  6. data/problem-specifications/exercises/isogram/canonical-data.json +3 -3
  7. data/problem-specifications/exercises/ocr-numbers/metadata.yml +1 -0
  8. data/problem-specifications/exercises/pascals-triangle/metadata.yml +1 -0
  9. data/problem-specifications/exercises/pov/metadata.yml +1 -0
  10. data/problem-specifications/exercises/rna-transcription/metadata.yml +1 -0
  11. data/problem-specifications/exercises/sgf-parsing/metadata.yml +1 -0
  12. data/tracks/c/exercises/all-your-base/src/example.c +14 -14
  13. data/tracks/c/exercises/all-your-base/src/example.h +2 -2
  14. data/tracks/ceylon/exercises/hamming/source/hamming/HammingTest.ceylon +1 -1
  15. data/tracks/ceylon/exercises/rna-transcription/source/rnatranscription/{RNAtest.ceylon → RNATest.ceylon} +0 -0
  16. data/tracks/cfml/.git +1 -0
  17. data/tracks/cfml/.gitignore +5 -0
  18. data/tracks/cfml/.travis.yml +18 -0
  19. data/tracks/cfml/CONTRIBUTING.md +10 -0
  20. data/tracks/cfml/LICENSE +21 -0
  21. data/tracks/cfml/README.md +92 -0
  22. data/tracks/cfml/bin/fetch-configlet +32 -0
  23. data/tracks/cfml/config/exercise_readme.go.tmpl +16 -0
  24. data/tracks/cfml/config/maintainers.json +13 -0
  25. data/tracks/cfml/config.json +223 -0
  26. data/tracks/cfml/docs/ABOUT.md +10 -0
  27. data/tracks/cfml/docs/EXERCISE_README_INSERT.md +15 -0
  28. data/tracks/cfml/docs/INSTALLATION.md +35 -0
  29. data/tracks/cfml/docs/LEARNING.md +37 -0
  30. data/tracks/cfml/docs/RESOURCES.md +29 -0
  31. data/tracks/cfml/docs/SNIPPET.txt +8 -0
  32. data/tracks/cfml/docs/TESTS.md +13 -0
  33. data/tracks/cfml/exercises/acronym/.meta/HINTS.md +0 -0
  34. data/tracks/cfml/exercises/acronym/Acronym.cfc +13 -0
  35. data/tracks/cfml/exercises/acronym/AcronymTest.cfc +43 -0
  36. data/tracks/cfml/exercises/acronym/Solution.cfc +22 -0
  37. data/tracks/cfml/exercises/acronym/SolutionTest.cfc +7 -0
  38. data/tracks/cfml/exercises/acronym/TestRunner.cfc +103 -0
  39. data/tracks/cfml/exercises/acronym/box.json +8 -0
  40. data/tracks/cfml/exercises/acronym/index.cfm +37 -0
  41. data/tracks/cfml/exercises/atbash-cipher/.meta/HINTS.md +0 -0
  42. data/tracks/cfml/exercises/atbash-cipher/AtbashCipher.cfc +14 -0
  43. data/tracks/cfml/exercises/atbash-cipher/AtbashCipherTest.cfc +71 -0
  44. data/tracks/cfml/exercises/atbash-cipher/Solution.cfc +56 -0
  45. data/tracks/cfml/exercises/atbash-cipher/SolutionTest.cfc +7 -0
  46. data/tracks/cfml/exercises/atbash-cipher/TestRunner.cfc +103 -0
  47. data/tracks/cfml/exercises/atbash-cipher/box.json +8 -0
  48. data/tracks/cfml/exercises/atbash-cipher/index.cfm +37 -0
  49. data/tracks/cfml/exercises/bob/.meta/HINTS.md +0 -0
  50. data/tracks/cfml/exercises/bob/Bob.cfc +13 -0
  51. data/tracks/cfml/exercises/bob/BobTest.cfc +115 -0
  52. data/tracks/cfml/exercises/bob/Solution.cfc +27 -0
  53. data/tracks/cfml/exercises/bob/SolutionTest.cfc +7 -0
  54. data/tracks/cfml/exercises/bob/TestRunner.cfc +103 -0
  55. data/tracks/cfml/exercises/bob/box.json +8 -0
  56. data/tracks/cfml/exercises/bob/index.cfm +37 -0
  57. data/tracks/cfml/exercises/diamond/.meta/HINTS.md +0 -0
  58. data/tracks/cfml/exercises/diamond/Diamond.cfc +13 -0
  59. data/tracks/cfml/exercises/diamond/DiamondTest.cfc +35 -0
  60. data/tracks/cfml/exercises/diamond/Solution.cfc +35 -0
  61. data/tracks/cfml/exercises/diamond/SolutionTest.cfc +7 -0
  62. data/tracks/cfml/exercises/diamond/TestRunner.cfc +103 -0
  63. data/tracks/cfml/exercises/diamond/box.json +8 -0
  64. data/tracks/cfml/exercises/diamond/index.cfm +37 -0
  65. data/tracks/cfml/exercises/difference-of-squares/.meta/HINTS.md +0 -0
  66. data/tracks/cfml/exercises/difference-of-squares/DifferenceOfSquares.cfc +18 -0
  67. data/tracks/cfml/exercises/difference-of-squares/DifferenceOfSquaresTest.cfc +63 -0
  68. data/tracks/cfml/exercises/difference-of-squares/Solution.cfc +28 -0
  69. data/tracks/cfml/exercises/difference-of-squares/SolutionTest.cfc +7 -0
  70. data/tracks/cfml/exercises/difference-of-squares/TestRunner.cfc +103 -0
  71. data/tracks/cfml/exercises/difference-of-squares/box.json +8 -0
  72. data/tracks/cfml/exercises/difference-of-squares/index.cfm +37 -0
  73. data/tracks/cfml/exercises/flatten-array/.meta/HINTS.md +0 -0
  74. data/tracks/cfml/exercises/flatten-array/FlattenArray.cfc +13 -0
  75. data/tracks/cfml/exercises/flatten-array/FlattenArrayTest.cfc +42 -0
  76. data/tracks/cfml/exercises/flatten-array/Solution.cfc +26 -0
  77. data/tracks/cfml/exercises/flatten-array/SolutionTest.cfc +7 -0
  78. data/tracks/cfml/exercises/flatten-array/TestRunner.cfc +103 -0
  79. data/tracks/cfml/exercises/flatten-array/box.json +8 -0
  80. data/tracks/cfml/exercises/flatten-array/index.cfm +37 -0
  81. data/tracks/cfml/exercises/gigasecond/.meta/HINTS.md +0 -0
  82. data/tracks/cfml/exercises/gigasecond/Gigasecond.cfc +13 -0
  83. data/tracks/cfml/exercises/gigasecond/GigasecondTest.cfc +39 -0
  84. data/tracks/cfml/exercises/gigasecond/Solution.cfc +16 -0
  85. data/tracks/cfml/exercises/gigasecond/SolutionTest.cfc +7 -0
  86. data/tracks/cfml/exercises/gigasecond/TestRunner.cfc +103 -0
  87. data/tracks/cfml/exercises/gigasecond/box.json +8 -0
  88. data/tracks/cfml/exercises/gigasecond/index.cfm +37 -0
  89. data/tracks/cfml/exercises/grains/.meta/HINTS.md +0 -0
  90. data/tracks/cfml/exercises/grains/Grains.cfc +14 -0
  91. data/tracks/cfml/exercises/grains/GrainsTest.cfc +63 -0
  92. data/tracks/cfml/exercises/grains/Solution.cfc +22 -0
  93. data/tracks/cfml/exercises/grains/SolutionTest.cfc +7 -0
  94. data/tracks/cfml/exercises/grains/TestRunner.cfc +103 -0
  95. data/tracks/cfml/exercises/grains/box.json +8 -0
  96. data/tracks/cfml/exercises/grains/index.cfm +37 -0
  97. data/tracks/cfml/exercises/hamming/.meta/HINTS.md +0 -0
  98. data/tracks/cfml/exercises/hamming/Hamming.cfc +13 -0
  99. data/tracks/cfml/exercises/hamming/HammingTest.cfc +75 -0
  100. data/tracks/cfml/exercises/hamming/Solution.cfc +25 -0
  101. data/tracks/cfml/exercises/hamming/SolutionTest.cfc +7 -0
  102. data/tracks/cfml/exercises/hamming/TestRunner.cfc +103 -0
  103. data/tracks/cfml/exercises/hamming/box.json +8 -0
  104. data/tracks/cfml/exercises/hamming/index.cfm +37 -0
  105. data/tracks/cfml/exercises/hello-world/HelloWorld.cfc +13 -0
  106. data/tracks/cfml/exercises/hello-world/HelloWorldTest.cfc +18 -0
  107. data/tracks/cfml/exercises/hello-world/Solution.cfc +13 -0
  108. data/tracks/cfml/exercises/hello-world/SolutionTest.cfc +7 -0
  109. data/tracks/cfml/exercises/hello-world/TestRunner.cfc +103 -0
  110. data/tracks/cfml/exercises/hello-world/box.json +8 -0
  111. data/tracks/cfml/exercises/hello-world/index.cfm +37 -0
  112. data/tracks/cfml/exercises/isogram/.meta/HINTS.md +0 -0
  113. data/tracks/cfml/exercises/isogram/Isogram.cfc +13 -0
  114. data/tracks/cfml/exercises/isogram/IsogramTest.cfc +55 -0
  115. data/tracks/cfml/exercises/isogram/Solution.cfc +23 -0
  116. data/tracks/cfml/exercises/isogram/SolutionTest.cfc +7 -0
  117. data/tracks/cfml/exercises/isogram/TestRunner.cfc +103 -0
  118. data/tracks/cfml/exercises/isogram/box.json +8 -0
  119. data/tracks/cfml/exercises/isogram/index.cfm +37 -0
  120. data/tracks/cfml/exercises/largest-series-product/.meta/HINTS.md +0 -0
  121. data/tracks/cfml/exercises/largest-series-product/LargestSeriesProduct.cfc +13 -0
  122. data/tracks/cfml/exercises/largest-series-product/LargestSeriesProductTest.cfc +75 -0
  123. data/tracks/cfml/exercises/largest-series-product/Solution.cfc +41 -0
  124. data/tracks/cfml/exercises/largest-series-product/SolutionTest.cfc +7 -0
  125. data/tracks/cfml/exercises/largest-series-product/TestRunner.cfc +103 -0
  126. data/tracks/cfml/exercises/largest-series-product/box.json +8 -0
  127. data/tracks/cfml/exercises/largest-series-product/index.cfm +37 -0
  128. data/tracks/cfml/exercises/leap/Leap.cfc +15 -0
  129. data/tracks/cfml/exercises/leap/LeapTest.cfc +39 -0
  130. data/tracks/cfml/exercises/leap/README.md +33 -0
  131. data/tracks/cfml/exercises/leap/Solution.cfc +19 -0
  132. data/tracks/cfml/exercises/leap/SolutionTest.cfc +7 -0
  133. data/tracks/cfml/exercises/leap/TestRunner.cfc +103 -0
  134. data/tracks/cfml/exercises/leap/box.json +8 -0
  135. data/tracks/cfml/exercises/leap/index.cfm +37 -0
  136. data/tracks/cfml/exercises/luhn/.meta/HINTS.md +0 -0
  137. data/tracks/cfml/exercises/luhn/Luhn.cfc +13 -0
  138. data/tracks/cfml/exercises/luhn/LuhnTest.cfc +67 -0
  139. data/tracks/cfml/exercises/luhn/Solution.cfc +38 -0
  140. data/tracks/cfml/exercises/luhn/SolutionTest.cfc +7 -0
  141. data/tracks/cfml/exercises/luhn/TestRunner.cfc +103 -0
  142. data/tracks/cfml/exercises/luhn/box.json +8 -0
  143. data/tracks/cfml/exercises/luhn/index.cfm +37 -0
  144. data/tracks/cfml/exercises/nth-prime/.meta/HINTS.md +0 -0
  145. data/tracks/cfml/exercises/nth-prime/NthPrime.cfc +13 -0
  146. data/tracks/cfml/exercises/nth-prime/NthPrimeTest.cfc +35 -0
  147. data/tracks/cfml/exercises/nth-prime/Solution.cfc +33 -0
  148. data/tracks/cfml/exercises/nth-prime/SolutionTest.cfc +7 -0
  149. data/tracks/cfml/exercises/nth-prime/TestRunner.cfc +103 -0
  150. data/tracks/cfml/exercises/nth-prime/box.json +8 -0
  151. data/tracks/cfml/exercises/nth-prime/index.cfm +37 -0
  152. data/tracks/cfml/exercises/pangram/.meta/HINTS.md +0 -0
  153. data/tracks/cfml/exercises/pangram/Pangram.cfc +13 -0
  154. data/tracks/cfml/exercises/pangram/PangramTest.cfc +55 -0
  155. data/tracks/cfml/exercises/pangram/Solution.cfc +21 -0
  156. data/tracks/cfml/exercises/pangram/SolutionTest.cfc +7 -0
  157. data/tracks/cfml/exercises/pangram/TestRunner.cfc +103 -0
  158. data/tracks/cfml/exercises/pangram/box.json +8 -0
  159. data/tracks/cfml/exercises/pangram/index.cfm +37 -0
  160. data/tracks/cfml/exercises/pig-latin/.meta/HINTS.md +0 -0
  161. data/tracks/cfml/exercises/pig-latin/PigLatin.cfc +13 -0
  162. data/tracks/cfml/exercises/pig-latin/PigLatinTest.cfc +115 -0
  163. data/tracks/cfml/exercises/pig-latin/Solution.cfc +30 -0
  164. data/tracks/cfml/exercises/pig-latin/SolutionTest.cfc +7 -0
  165. data/tracks/cfml/exercises/pig-latin/TestRunner.cfc +103 -0
  166. data/tracks/cfml/exercises/pig-latin/box.json +8 -0
  167. data/tracks/cfml/exercises/pig-latin/index.cfm +37 -0
  168. data/tracks/cfml/exercises/raindrops/.meta/HINTS.md +0 -0
  169. data/tracks/cfml/exercises/raindrops/Raindrops.cfc +13 -0
  170. data/tracks/cfml/exercises/raindrops/RaindropsTest.cfc +87 -0
  171. data/tracks/cfml/exercises/raindrops/Solution.cfc +33 -0
  172. data/tracks/cfml/exercises/raindrops/SolutionTest.cfc +7 -0
  173. data/tracks/cfml/exercises/raindrops/TestRunner.cfc +103 -0
  174. data/tracks/cfml/exercises/raindrops/box.json +8 -0
  175. data/tracks/cfml/exercises/raindrops/index.cfm +37 -0
  176. data/tracks/cfml/exercises/rna-transcription/.meta/HINTS.md +0 -0
  177. data/tracks/cfml/exercises/rna-transcription/RnaTranscription.cfc +13 -0
  178. data/tracks/cfml/exercises/rna-transcription/RnaTranscriptionTest.cfc +47 -0
  179. data/tracks/cfml/exercises/rna-transcription/Solution.cfc +35 -0
  180. data/tracks/cfml/exercises/rna-transcription/SolutionTest.cfc +7 -0
  181. data/tracks/cfml/exercises/rna-transcription/TestRunner.cfc +103 -0
  182. data/tracks/cfml/exercises/rna-transcription/box.json +8 -0
  183. data/tracks/cfml/exercises/rna-transcription/index.cfm +37 -0
  184. data/tracks/cfml/exercises/saddle-points/.meta/HINTS.md +0 -0
  185. data/tracks/cfml/exercises/saddle-points/SaddlePoints.cfc +13 -0
  186. data/tracks/cfml/exercises/saddle-points/SaddlePointsTest.cfc +35 -0
  187. data/tracks/cfml/exercises/saddle-points/Solution.cfc +59 -0
  188. data/tracks/cfml/exercises/saddle-points/SolutionTest.cfc +7 -0
  189. data/tracks/cfml/exercises/saddle-points/TestRunner.cfc +103 -0
  190. data/tracks/cfml/exercises/saddle-points/box.json +8 -0
  191. data/tracks/cfml/exercises/saddle-points/index.cfm +37 -0
  192. data/tracks/cfml/exercises/scrabble-score/.meta/HINTS.md +0 -0
  193. data/tracks/cfml/exercises/scrabble-score/ScrabbleScore.cfc +13 -0
  194. data/tracks/cfml/exercises/scrabble-score/ScrabbleScoreTest.cfc +59 -0
  195. data/tracks/cfml/exercises/scrabble-score/Solution.cfc +50 -0
  196. data/tracks/cfml/exercises/scrabble-score/SolutionTest.cfc +7 -0
  197. data/tracks/cfml/exercises/scrabble-score/TestRunner.cfc +103 -0
  198. data/tracks/cfml/exercises/scrabble-score/box.json +8 -0
  199. data/tracks/cfml/exercises/scrabble-score/index.cfm +37 -0
  200. data/tracks/cfml/exercises/secret-handshake/.meta/HINTS.md +0 -0
  201. data/tracks/cfml/exercises/secret-handshake/SecretHandshake.cfc +13 -0
  202. data/tracks/cfml/exercises/secret-handshake/SecretHandshakeTest.cfc +63 -0
  203. data/tracks/cfml/exercises/secret-handshake/Solution.cfc +31 -0
  204. data/tracks/cfml/exercises/secret-handshake/SolutionTest.cfc +7 -0
  205. data/tracks/cfml/exercises/secret-handshake/TestRunner.cfc +103 -0
  206. data/tracks/cfml/exercises/secret-handshake/box.json +8 -0
  207. data/tracks/cfml/exercises/secret-handshake/index.cfm +37 -0
  208. data/tracks/cfml/exercises/space-age/.meta/HINTS.md +0 -0
  209. data/tracks/cfml/exercises/space-age/Solution.cfc +28 -0
  210. data/tracks/cfml/exercises/space-age/SolutionTest.cfc +7 -0
  211. data/tracks/cfml/exercises/space-age/SpaceAge.cfc +13 -0
  212. data/tracks/cfml/exercises/space-age/SpaceAgeTest.cfc +47 -0
  213. data/tracks/cfml/exercises/space-age/TestRunner.cfc +103 -0
  214. data/tracks/cfml/exercises/space-age/box.json +8 -0
  215. data/tracks/cfml/exercises/space-age/index.cfm +37 -0
  216. data/tracks/cfml/exercises/sum-of-multiples/.meta/HINTS.md +0 -0
  217. data/tracks/cfml/exercises/sum-of-multiples/Solution.cfc +27 -0
  218. data/tracks/cfml/exercises/sum-of-multiples/SolutionTest.cfc +7 -0
  219. data/tracks/cfml/exercises/sum-of-multiples/SumOfMultiples.cfc +13 -0
  220. data/tracks/cfml/exercises/sum-of-multiples/SumOfMultiplesTest.cfc +63 -0
  221. data/tracks/cfml/exercises/sum-of-multiples/TestRunner.cfc +103 -0
  222. data/tracks/cfml/exercises/sum-of-multiples/box.json +8 -0
  223. data/tracks/cfml/exercises/sum-of-multiples/index.cfm +37 -0
  224. data/tracks/cfml/exercises/triangle/.meta/HINTS.md +0 -0
  225. data/tracks/cfml/exercises/triangle/Solution.cfc +53 -0
  226. data/tracks/cfml/exercises/triangle/SolutionTest.cfc +7 -0
  227. data/tracks/cfml/exercises/triangle/TestRunner.cfc +103 -0
  228. data/tracks/cfml/exercises/triangle/Triangle.cfc +18 -0
  229. data/tracks/cfml/exercises/triangle/TriangleTest.cfc +95 -0
  230. data/tracks/cfml/exercises/triangle/box.json +8 -0
  231. data/tracks/cfml/exercises/triangle/index.cfm +37 -0
  232. data/tracks/cfml/exercises/word-count/.meta/HINTS.md +0 -0
  233. data/tracks/cfml/exercises/word-count/Solution.cfc +22 -0
  234. data/tracks/cfml/exercises/word-count/SolutionTest.cfc +7 -0
  235. data/tracks/cfml/exercises/word-count/TestRunner.cfc +103 -0
  236. data/tracks/cfml/exercises/word-count/WordCount.cfc +13 -0
  237. data/tracks/cfml/exercises/word-count/WordCountTest.cfc +55 -0
  238. data/tracks/cfml/exercises/word-count/box.json +8 -0
  239. data/tracks/cfml/exercises/word-count/index.cfm +37 -0
  240. data/tracks/cfml/img/icon.png +0 -0
  241. data/tracks/cfml/tasks/GenerateTests.cfc +179 -0
  242. data/tracks/cfml/tasks/ScaffoldExercise.cfc +85 -0
  243. data/tracks/cfml/tasks/TestAllSolutions.cfc +24 -0
  244. data/tracks/cfml/tasks/exercise_template/.meta/HINTS.md +0 -0
  245. data/tracks/cfml/tasks/exercise_template/@@name@@.cfc +13 -0
  246. data/tracks/cfml/tasks/exercise_template/@@name@@Test.cfc +15 -0
  247. data/tracks/cfml/tasks/exercise_template/Solution.cfc +6 -0
  248. data/tracks/cfml/tasks/exercise_template/SolutionTest.cfc +7 -0
  249. data/tracks/cfml/tasks/exercise_template/TestRunner.cfc +103 -0
  250. data/tracks/cfml/tasks/exercise_template/box.json +8 -0
  251. data/tracks/cfml/tasks/exercise_template/index.cfm +37 -0
  252. data/tracks/coldfusion/docs/ABOUT.md +8 -6
  253. data/tracks/csharp/docs/GENERATORS.md +7 -0
  254. data/tracks/csharp/exercises/clock/ClockTest.cs +15 -15
  255. data/tracks/csharp/exercises/nucleotide-count/Example.cs +10 -11
  256. data/tracks/csharp/exercises/nucleotide-count/NucleotideCount.cs +2 -7
  257. data/tracks/csharp/exercises/nucleotide-count/NucleotideCountTest.cs +37 -47
  258. data/tracks/csharp/exercises/pig-latin/Example.cs +1 -1
  259. data/tracks/csharp/exercises/pig-latin/PigLatinTest.cs +19 -7
  260. data/tracks/csharp/exercises/sum-of-multiples/SumOfMultiplesTest.cs +7 -1
  261. data/tracks/csharp/exercises/tournament/Example.cs +1 -1
  262. data/tracks/csharp/exercises/tournament/TournamentTest.cs +151 -68
  263. data/tracks/csharp/exercises/triangle/Example.cs +26 -8
  264. data/tracks/csharp/exercises/triangle/Triangle.cs +16 -1
  265. data/tracks/csharp/exercises/triangle/TriangleTest.cs +44 -30
  266. data/tracks/csharp/generators/Exercise.cs +6 -1
  267. data/tracks/csharp/generators/Exercises/Clock.cs +17 -1
  268. data/tracks/csharp/generators/Exercises/NucleotideCount.cs +61 -0
  269. data/tracks/csharp/generators/Exercises/Tournament.cs +66 -0
  270. data/tracks/csharp/generators/Exercises/Triangle.cs +36 -0
  271. data/tracks/dart/config.json +15 -2
  272. data/tracks/dart/exercises/raindrops/lib/example.dart +23 -0
  273. data/tracks/dart/exercises/raindrops/lib/raindrops.dart +3 -0
  274. data/tracks/dart/exercises/raindrops/pubspec.lock +281 -0
  275. data/tracks/dart/exercises/raindrops/pubspec.yaml +3 -0
  276. data/tracks/dart/exercises/raindrops/test/raindrops_test.dart +94 -0
  277. data/tracks/delphi/exercises/pig-latin/uPigLatinExample.pas +1 -25
  278. data/tracks/haskell/config.json +9 -0
  279. data/tracks/haskell/exercises/acronym/README.md +0 -1
  280. data/tracks/haskell/exercises/all-your-base/README.md +1 -1
  281. data/tracks/haskell/exercises/allergies/README.md +0 -1
  282. data/tracks/haskell/exercises/alphametics/README.md +2 -2
  283. data/tracks/haskell/exercises/atbash-cipher/README.md +2 -1
  284. data/tracks/haskell/exercises/beer-song/README.md +1 -1
  285. data/tracks/haskell/exercises/binary/README.md +2 -0
  286. data/tracks/haskell/exercises/bowling/README.md +20 -6
  287. data/tracks/haskell/exercises/collatz-conjecture/README.md +1 -1
  288. data/tracks/haskell/exercises/connect/README.md +1 -1
  289. data/tracks/haskell/exercises/crypto-square/README.md +4 -4
  290. data/tracks/haskell/exercises/diamond/README.md +113 -0
  291. data/tracks/haskell/exercises/diamond/examples/success-standard/package.yaml +16 -0
  292. data/tracks/haskell/exercises/diamond/examples/success-standard/src/Diamond.hs +16 -0
  293. data/tracks/haskell/exercises/diamond/package.yaml +20 -0
  294. data/tracks/haskell/exercises/diamond/src/Diamond.hs +4 -0
  295. data/tracks/haskell/exercises/diamond/stack.yaml +1 -0
  296. data/tracks/haskell/exercises/diamond/test/Tests.hs +109 -0
  297. data/tracks/haskell/exercises/etl/README.md +3 -1
  298. data/tracks/haskell/exercises/food-chain/README.md +1 -1
  299. data/tracks/haskell/exercises/go-counting/README.md +1 -1
  300. data/tracks/haskell/exercises/grade-school/README.md +0 -1
  301. data/tracks/haskell/exercises/grains/README.md +0 -1
  302. data/tracks/haskell/exercises/house/README.md +1 -2
  303. data/tracks/haskell/exercises/isogram/README.md +2 -1
  304. data/tracks/haskell/exercises/kindergarten-garden/README.md +3 -3
  305. data/tracks/haskell/exercises/leap/README.md +1 -1
  306. data/tracks/haskell/exercises/linked-list/README.md +10 -10
  307. data/tracks/haskell/exercises/luhn/README.md +7 -7
  308. data/tracks/haskell/exercises/matrix/README.md +6 -4
  309. data/tracks/haskell/exercises/meetup/README.md +1 -2
  310. data/tracks/haskell/exercises/nucleotide-count/README.md +8 -22
  311. data/tracks/haskell/exercises/ocr-numbers/README.md +6 -6
  312. data/tracks/haskell/exercises/octal/README.md +6 -2
  313. data/tracks/haskell/exercises/palindrome-products/README.md +12 -6
  314. data/tracks/haskell/exercises/pangram/README.md +1 -1
  315. data/tracks/haskell/exercises/pascals-triangle/README.md +2 -2
  316. data/tracks/haskell/exercises/phone-number/README.md +3 -2
  317. data/tracks/haskell/exercises/pov/README.md +3 -3
  318. data/tracks/haskell/exercises/pythagorean-triplet/README.md +3 -3
  319. data/tracks/haskell/exercises/queen-attack/README.md +1 -1
  320. data/tracks/haskell/exercises/rna-transcription/README.md +1 -1
  321. data/tracks/haskell/exercises/roman-numerals/README.md +1 -1
  322. data/tracks/haskell/exercises/run-length-encoding/README.md +4 -4
  323. data/tracks/haskell/exercises/saddle-points/README.md +1 -1
  324. data/tracks/haskell/exercises/scrabble-score/README.md +3 -1
  325. data/tracks/haskell/exercises/secret-handshake/README.md +1 -1
  326. data/tracks/haskell/exercises/sgf-parsing/README.md +4 -4
  327. data/tracks/haskell/exercises/simple-cipher/README.md +1 -1
  328. data/tracks/haskell/exercises/spiral-matrix/README.md +2 -2
  329. data/tracks/haskell/exercises/triangle/README.md +9 -6
  330. data/tracks/haskell/exercises/trinary/README.md +1 -1
  331. data/tracks/haskell/exercises/word-count/README.md +1 -2
  332. data/tracks/haskell/exercises/wordy/README.md +0 -5
  333. data/tracks/java/config.json +56 -9
  334. data/tracks/java/exercises/binary-search-tree/src/test/java/BSTTest.java +4 -4
  335. data/tracks/javascript/exercises/two-bucket/example.js +66 -69
  336. data/tracks/javascript/exercises/two-bucket/two-bucket.spec.js +18 -18
  337. data/tracks/julia/config.json +1 -0
  338. data/tracks/julia/docs/ABOUT.md +3 -8
  339. data/tracks/prolog/README.md +1 -1
  340. data/tracks/purescript/.travis.yml +1 -0
  341. data/tracks/purescript/README.md +9 -0
  342. data/tracks/purescript/bin/check-bower.sh +42 -0
  343. data/tracks/purescript/bin/test-separate.sh +46 -0
  344. data/tracks/python/README.md +2 -2
  345. data/tracks/python/exercises/all-your-base/all_your_base.py +2 -0
  346. data/tracks/python/exercises/atbash-cipher/atbash_cipher.py +2 -2
  347. data/tracks/python/exercises/complex-numbers/complex_numbers_test.py +2 -2
  348. data/tracks/python/exercises/complex-numbers/example.py +2 -2
  349. data/tracks/python/exercises/gigasecond/gigasecond.py +1 -1
  350. data/tracks/python/exercises/hamming/hamming.py +1 -1
  351. data/tracks/python/exercises/hexadecimal/hexadecimal.py +1 -1
  352. data/tracks/python/exercises/leap/leap.py +1 -1
  353. data/tracks/python/exercises/meetup/meetup.py +1 -1
  354. data/tracks/python/exercises/phone-number/example.py +4 -2
  355. data/tracks/python/exercises/phone-number/phone_number_test.py +47 -16
  356. data/tracks/python/exercises/pig-latin/pig_latin.py +1 -1
  357. data/tracks/python/exercises/scrabble-score/scrabble_score.py +1 -1
  358. data/tracks/python/exercises/wordy/wordy.py +1 -1
  359. data/tracks/scala/exercises/meetup/example.scala +29 -10
  360. data/tracks/scala/exercises/meetup/src/main/scala/Meetup.scala +23 -0
  361. data/tracks/scala/exercises/meetup/src/test/scala/MeetupTest.scala +273 -183
  362. data/tracks/sml/config.json +13 -0
  363. data/tracks/sml/exercises/anagram/README.md +21 -5
  364. data/tracks/sml/exercises/anagram/anagram.sml +2 -6
  365. data/tracks/sml/exercises/anagram/example.sml +29 -24
  366. data/tracks/sml/exercises/anagram/test.sml +56 -50
  367. data/tracks/sml/exercises/anagram/testlib.sml +159 -0
  368. data/tracks/sml/exercises/diamond/README.md +89 -0
  369. data/tracks/sml/exercises/diamond/diamond.sml +2 -0
  370. data/tracks/sml/exercises/diamond/example.sml +25 -0
  371. data/tracks/sml/exercises/diamond/test.sml +27 -0
  372. data/tracks/sml/exercises/diamond/testlib.sml +159 -0
  373. data/tracks/sml/exercises/raindrops/raindrops.sml +2 -2
  374. data/tracks/sml/exercises/raindrops/test.sml +66 -95
  375. data/tracks/sml/exercises/raindrops/testlib.sml +159 -0
  376. metadata +265 -3
@@ -0,0 +1,179 @@
1
+ /**
2
+ * I scaffold a new exercise from the template.
3
+ */
4
+ component {
5
+
6
+ function run(
7
+ slug,
8
+ boolean all=false
9
+ ) {
10
+ var repoRootPath = expandPath( getDirectoryFromPath( getCurrentTemplatePath() ) & '../' );
11
+ var problemSpecsPath = expandPath( getDirectoryFromPath( getCurrentTemplatePath() ) & '../../problem-specifications' );
12
+
13
+ if( !directoryExists( problemSpecsPath ) ){
14
+ error( 'Cannot find [problem-specifications] repo. It needs to be git cloned to [#problemSpecsPath#]' );
15
+ }
16
+
17
+ if( all ) {
18
+
19
+ // Get an array of all the excercise names
20
+ var exercises = directoryList( expandPath( getDirectoryFromPath( getCurrentTemplatePath() ) & '../exercises' ) )
21
+ .map( function( path ) {
22
+ return path.listLast( '/\' );
23
+ } );
24
+
25
+ } else {
26
+
27
+ // Acquire slug
28
+ if( isNull( arguments.slug ) ) {
29
+ arguments.slug = ask( 'Exercise slug as defined by Excercism. Ex: "hello-world": ' );
30
+ }
31
+ var exercises = [ slug ];
32
+
33
+ }
34
+
35
+ exercises.each( function( slug ) {
36
+
37
+ try {
38
+
39
+ // Slug of hello-world defaults to name of HelloWorld
40
+ var exerciseName = arguments.slug
41
+ .listToArray( '-' )
42
+ .map( function( i ){
43
+ return i.left( 1 ).uCase() & i.right( -1 ).lCase();
44
+ } )
45
+ .toList( '' );
46
+
47
+ var exercisePath = problemSpecsPath & '/exercises/' & slug;
48
+ if( !directoryExists( exercisePath ) ){
49
+ error( 'Cannot find exercise [#slug#] in problem-specifications repo. Tests not generated.' );
50
+ }
51
+
52
+ var canonicalDataPath = exercisePath & '/canonical-data.json';
53
+ if( !fileExists( canonicalDataPath ) ){
54
+ error( 'Cannot find [canonical-data.json] for this slug. No tests will be generated' );
55
+ }
56
+
57
+ var canonicalData = deserializeJSON( fileRead( canonicalDataPath ) );
58
+ var testCases = generateCases( canonicalData.cases );
59
+
60
+ var testStub = fileRead( repoRootPath & '/tasks/exercise_template/@@name@@Test.cfc' );
61
+ testStub = testStub.replace( '@@name@@', exerciseName, 'all' );
62
+ testStub = testStub.replace( '@@testCases@@', testCases, 'all' );
63
+ var targetExercisePath = repoRootPath & 'exercises/' & slug;
64
+ var newTestPath = targetExercisePath & '/' & exerciseName & 'Test.cfc';
65
+
66
+ if( !directoryExists( targetExercisePath ) ) {
67
+ error( 'Target exercise does not exist! [#targetExercisePath#]' );
68
+ }
69
+
70
+ fileWrite( newTestPath, testStub );
71
+
72
+ print.greenLine( 'Test generated!' )
73
+ .indentedYellowLine( newTestPath )
74
+ .toConsole();
75
+ } catch( 'commandException' var e ) {
76
+ print.boldRedLine( e.message )
77
+ .line();
78
+ }
79
+
80
+ } ); // End exercises.each()
81
+ }
82
+
83
+ private function generateCases( cases, level=1 ) {
84
+ var CRLF = chr( 13 ) & chr( 10 );
85
+ var testCases = ''
86
+
87
+ cases.each( function( case ) {
88
+
89
+ // Nested spec
90
+ if( case.keyExists( 'cases' ) ) {
91
+
92
+ testCases &= "#CRLF##repeatString( chr( 9 ), level )# describe( #generateDescription( case.description )#, function(){
93
+ #generateCases( case.cases, level+1 )#
94
+ #repeatString( chr( 9 ), level )# });#CRLF#";
95
+
96
+ } else {
97
+ case.expected = case.expected ?: '__NULL__';
98
+ // Don't adjust whitespace
99
+ testCases &= "#CRLF##repeatString( chr( 9 ), level )# it( #generateDescription( case.description )#, function(){#CRLF#";
100
+ // Special check for when error should be tested
101
+ if( isStruct( case.expected ) && case.expected.keyExists( 'error' ) ) {
102
+ testCases &= "#repeatString( chr( 9 ), level )# expect( function(){ SUT.#case.property#(#generateInput( case )#); } ).#generateExpectation( case.expected )#;#CRLF#";
103
+ // "normal" expectation
104
+ } else {
105
+ testCases &= "#repeatString( chr( 9 ), level )# expect( SUT.#case.property#(#generateInput( case )#) ).#generateExpectation( case.expected )#;#CRLF#";
106
+ }
107
+ testCases &= "#repeatString( chr( 9 ), level )# });#CRLF#";
108
+ }
109
+
110
+ } );
111
+
112
+ return testCases;
113
+ }
114
+
115
+ private function generateDescription( description ) {
116
+ return escapeString( description );
117
+ }
118
+
119
+ private function generateInput( case ) {
120
+ var thisInput = '';
121
+ for( var key in case ) {
122
+ if( !listFindNoCase( 'description,property,expected,cases,comments', key ) && !isNull( case[ key ] ) ) {
123
+ thisInput = thisInput.listAppend( "#key#=#escapeString( case[ key ] )#" );
124
+ }
125
+ }
126
+ if( thisInput.len() ) {
127
+ return ' ' & thisInput.listChangeDelims( ', ', ',' ) & ' ';
128
+ } else {
129
+ return thisInput;
130
+ }
131
+ }
132
+
133
+ private function generateExpectation( expected ) {
134
+ if( isSimpleValue( expected ) && compareNoCase( expected, 'true' ) == 0 ) {
135
+ return 'toBeTrue()';
136
+ } else if( isSimpleValue( expected ) && compareNoCase( expected, 'false' ) == 0 ) {
137
+ return 'toBeFalse()';
138
+ } else if( isSimpleValue( expected) && expected == '__NULL__' ) {
139
+ return 'toBeNull()';
140
+ } else if( isStruct( expected ) && expected.keyExists( 'error' ) ) {
141
+ return 'toThrow( message=#escapeString( expected.error )# )';
142
+ } else {
143
+ return "toBe( #escapeString( expected )# )";
144
+ }
145
+
146
+ }
147
+
148
+ private function escapeString( myString ) {
149
+ if( isSimpleValue( myString ) ) {
150
+ myString = replace( myString, "'", "''", "all" );
151
+ myString = replace( myString, '##', '####', 'all' );
152
+ myString = replace( myString, chr( 13 ), '##chr( 13 )##', 'all' );
153
+ myString = replace( myString, chr( 10 ), '##chr( 10 )##', 'all' );
154
+ return "'" & myString & "'";
155
+ } else {
156
+ return convertJSONEscapesToCFML( serializeJSON( myString ) );
157
+ }
158
+ }
159
+
160
+
161
+ // A complex value serialized as JSON differs from CFML struct literals in that
162
+ // double quotes are \" instead of "". Any escaped double quotes must be converted
163
+ // to the CFML version to work as an object literal.
164
+ private function convertJSONEscapesToCFML( required string arg ) {
165
+ arguments.arg = replaceNoCase( arguments.arg, '\\', '__double_backslash_', 'all' );
166
+ arguments.arg = replaceNoCase( arguments.arg, '\/', '/', 'all' );
167
+ arguments.arg = replaceNoCase( arguments.arg, '\"', '""', 'all' );
168
+ arguments.arg = replaceNoCase( arguments.arg, '\t', ' ', 'all' );
169
+ arguments.arg = replaceNoCase( arguments.arg, '\n', chr(13)&chr(10), 'all' );
170
+ arguments.arg = replaceNoCase( arguments.arg, '\r', chr(13), 'all' );
171
+ arguments.arg = replaceNoCase( arguments.arg, '\f', chr(12), 'all' );
172
+ arguments.arg = replaceNoCase( arguments.arg, '\b', chr(8), 'all' );
173
+ // This doesn't work-- I'd need to do it in a loop and replace each one individually. Meh...
174
+ // arguments.arg = reReplaceNoCase( arguments.arg, '\\u([0-9a-f]{4})', chr( inputBaseN( '\1', 16 ) ), 'all' );
175
+ arguments.arg = replaceNoCase( arguments.arg, '__double_backslash_', '\', 'all' );
176
+ return arguments.arg;
177
+ }
178
+
179
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * I scaffold a new exercise from the template.
3
+ */
4
+ component {
5
+
6
+ function run(
7
+ slug,
8
+ difficulty,
9
+ uuid=createGUID()
10
+ ) {
11
+ var repoRootPath = expandPath( getDirectoryFromPath( getCurrentTemplatePath() ) & '../' );
12
+
13
+ // Acquire slug
14
+ if( isNull( arguments.slug ) ) {
15
+ arguments.slug = ask( 'Exercise slug as defined by Excercism. Ex: "hello-world": ' );
16
+ }
17
+
18
+ // Slug of hello-world defaults to name of HelloWorld
19
+ var exerciseName = arguments.slug
20
+ .listToArray( '-' )
21
+ .map( function( i ){
22
+ return i.left( 1 ).uCase() & i.right( -1 ).lCase();
23
+ } )
24
+ .toList( '' );
25
+
26
+ // Acquire diffculty
27
+ if( isNull( arguments.difficulty ) ) {
28
+ arguments.difficulty = ask( message='Difficulty: ', defaultResponse=1 );
29
+ }
30
+
31
+ // Validation to prevent duplicate runs
32
+ var exerciseDirectory = repoRootPath & 'exercises/' & arguments.slug;
33
+ if( directoryExists( exerciseDirectory ) ) {
34
+ error( 'An exercise named [#arguments.slug#] already exists!' );
35
+ }
36
+
37
+ // Add this exercise to config.json
38
+ var configJSON = deserializeJSON( fileRead( repoRootPath & '/config.json' ) );
39
+ configJSON.exercises.append( {
40
+ "uuid": arguments.uuid,
41
+ "difficulty": arguments.difficulty+0,
42
+ "slug": arguments.slug,
43
+ "topics": []
44
+ } );
45
+ fileWrite( repoRootPath & '/config.json', formatterUtil.formatJSON( json=configJSON, indent=' ' , lineEnding=chr( 10 ) ) );
46
+
47
+ // Create exercise scaffold
48
+ directoryCreate( exerciseDirectory );
49
+ directoryCopy( repoRootPath & '/tasks/exercise_template', exerciseDirectory, true );
50
+
51
+ // Perform Token replacements
52
+ command( 'tokenReplace' )
53
+ .params( '**', '@@name@@', exerciseName )
54
+ .inWorkingDirectory( exerciseDirectory )
55
+ .run();
56
+
57
+ directoryList( exerciseDirectory, true )
58
+ .each( function( path ){
59
+ if( path.findNoCase( '@@name@@' ) ) {
60
+ fileMove( path, path.replaceNoCase( '@@name@@', exerciseName, 'all' ) );
61
+ }
62
+ } );
63
+
64
+ print.boldGreenLine( 'New exercise created!' )
65
+ .line()
66
+ .greenLine( 'The exercise is located here: ' )
67
+ .indentedYellowLine( exerciseDirectory )
68
+ .line()
69
+ .greenLine( 'Create a sample solution here: ' )
70
+ .indentedYellowLine( exerciseDirectory & '/Solution.cfc' )
71
+ .line()
72
+ .greenLine( 'Test your solution with this command: ' )
73
+ .indentedYellowLine( 'box task run TestRunner --:solution' )
74
+ .line()
75
+ .toConsole();
76
+
77
+ // Generate test suite
78
+ command( 'task run' )
79
+ .params( 'GenerateTests', 'run', slug )
80
+ .inWorkingDirectory( repoRootPath & '/tasks' )
81
+ .run();
82
+
83
+ }
84
+
85
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * I test all the solutions in each exercise to make sure they all pass.
3
+ */
4
+ component {
5
+
6
+ function run() {
7
+ // Get an array of all the excercise names
8
+ var exercises = directoryList( expandPath( getDirectoryFromPath( getCurrentTemplatePath() ) & '../exercises' ) );
9
+
10
+ // If there's a testrunner task in them, run it. If any of the tasks fail, the exit code will come back as 1
11
+ exercises.each( function( path ) {
12
+ if( fileExists( path & '/TestRunner.cfc' ) ) {
13
+ command( 'task run' )
14
+ .params( 'TestRunner' )
15
+ // Specifically as the task runners to run the SolutionTest
16
+ .flags( ':solution' )
17
+ .inWorkingDirectory( path )
18
+ .run();
19
+ }
20
+ } );
21
+
22
+ }
23
+
24
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Your implmentation of the @@name@@ exercise
3
+ */
4
+ component {
5
+
6
+ /**
7
+ * @returns
8
+ */
9
+ function stubMethodName() {
10
+ // Implement me here
11
+ }
12
+
13
+ }
@@ -0,0 +1,15 @@
1
+ component extends="testbox.system.BaseSpec" {
2
+
3
+ function beforeAll(){
4
+ SUT = createObject( '@@name@@' );
5
+ }
6
+
7
+ function run(){
8
+
9
+ describe( "My @@name@@ class", function(){
10
+ @@testCases@@
11
+ });
12
+
13
+ }
14
+
15
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Here is an example solution for the @@name@@ exercise
3
+ */
4
+ component {
5
+
6
+ }
@@ -0,0 +1,7 @@
1
+ component extends="@@name@@Test" {
2
+
3
+ function beforeAll(){
4
+ SUT = createObject( 'Solution' );
5
+ }
6
+
7
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * I am a CommandBox task runner which you can use to test your implementation of this exercise against the
3
+ * provided test suite. To use me, open the CommandBox CLI and run this:
4
+ *
5
+ * CommandBox> task run TestRunner
6
+ *
7
+ * To start up a test watcher that will automatically rerun the test suite every time you save a file change, run this:
8
+ *
9
+ * CommandBox> task run TestRunner --watcher
10
+ *
11
+ */
12
+ component {
13
+
14
+ /**
15
+ * @solution Runs the tests against the solution
16
+ * @watcher Start up a file watch that re-runs the tests on file changes. Use Ctrl-C to stop
17
+ */
18
+ function run( boolean solution=false, boolean watcher=false ) {
19
+
20
+ ensureTestBox();
21
+
22
+ if( watcher ) {
23
+
24
+ // Tabula rasa
25
+ command( 'cls' ).run();
26
+
27
+ // Start watcher
28
+ watch()
29
+ .paths( '*.cfc' )
30
+ .inDirectory( getCWD() )
31
+ .withDelay( 500 )
32
+ .onChange( function() {
33
+
34
+ // Clear the screen
35
+ command( 'cls' )
36
+ .run();
37
+
38
+ // This is neccessary so changes to tests get picked up right away.
39
+ pagePoolClear();
40
+
41
+ runTests( solution );
42
+
43
+ } )
44
+ .start();
45
+
46
+ } else {
47
+ runTests( solution );
48
+ }
49
+
50
+ }
51
+
52
+ /**
53
+ * Make sure the TestBox framework is installed
54
+ */
55
+ private function ensureTestBox() {
56
+ var excerciseRoot = getCWD();
57
+ var testBoxRoot = excerciseRoot & '/testbox';
58
+
59
+ if( !directoryExists( testBoxRoot ) ) {
60
+
61
+ print.boldYellowLine( 'Installing some missing dependencies for you!' ).toConsole();
62
+ command( 'install' )
63
+ .inWorkingDirectory( excerciseRoot )
64
+ .run();
65
+ }
66
+
67
+ // Bootstrap TestBox framework
68
+ filesystemUtil.createMapping( '/testbox', testBoxRoot );
69
+ }
70
+
71
+ /**
72
+ * Invoke TestBox to run the test suite
73
+ */
74
+ private function runTests( boolean solution=false ) {
75
+
76
+ // Create TestBox and run the tests
77
+ testData = new testbox.system.TestBox()
78
+ .runRaw( directory = {
79
+ // Find all CFCs...
80
+ mapping = filesystemUtil.makePathRelative( getCWD() ),
81
+ // ... in this directory ...
82
+ recurse = false,
83
+ // ... whose name ends in "test"
84
+ filter = function( path ) {
85
+ return path.reFind( ( solution ? 'Solution' : '' ) & 'Test.cfc$' );
86
+ }
87
+ } )
88
+ .getMemento();
89
+
90
+ // Print out the results with ANSI formatting for the CLI
91
+ getInstance( 'CLIRenderer@testbox-commands' )
92
+ .render( print, testData, true );
93
+
94
+ print.toConsole();
95
+
96
+ // Set proper exit code
97
+ if( testData.totalFail || testData.totalError ) {
98
+ setExitCode( 1 );
99
+ }
100
+ }
101
+
102
+ }
103
+
@@ -0,0 +1,8 @@
1
+ {
2
+ "dependencies":{
3
+ "testbox":"^2.5.0+107"
4
+ },
5
+ "installPaths":{
6
+ "testbox":"testbox"
7
+ }
8
+ }
@@ -0,0 +1,37 @@
1
+ <!---
2
+
3
+ This file will only be used if you want to start up a web server in this directory. You can do so by running:
4
+
5
+ $> box
6
+ CommandBox> install
7
+ CommandBox> server start
8
+
9
+ However, this is not necessary unless you really just want to use the HTML reporters on TestBox.
10
+ Ideally, you'll skip the need for this file entirely and just run the tests directly frm the CLI like this:
11
+
12
+ CommandBox> task run TestRunner
13
+
14
+ --->
15
+ <cfsetting showDebugOutput="false">
16
+ <cfparam name="url.reporter" default="simple">
17
+ <cfscript>
18
+ // get a list of all CFCs in this folder whose name looks like "XXXTest.cfc"
19
+ // And turn it into compnent path relative to the web root
20
+ url.bundles = directoryList(
21
+ path=expandPath( '/' ),
22
+ filter='*Test.cfc' )
23
+ .map( function( path ) {
24
+ return path
25
+ .replaceNoCase( expandPath( '/' ), '' )
26
+ .left( -4 )
27
+ } )
28
+ .toList();
29
+ </cfscript>
30
+
31
+ <!--- Ensure TestBox --->
32
+ <cfif fileExists( "/testbox/system/runners/HTMLRunner.cfm" )>
33
+ <!--- Include the TestBox HTML Runner --->
34
+ <cfinclude template="/testbox/system/runners/HTMLRunner.cfm">
35
+ <cfelse>
36
+ Oops, you don't have TestBox installed yet! Please run <b>box install</b> from the root of your excercise folder and refresh this page.
37
+ </cfif>
@@ -1,8 +1,10 @@
1
- ColdFusion (CFML) is a JVM scripting language whose syntax is similar to C or JavaScript. It JIT compiles to byte code that runs on the JVM but is dynamic and loosely typed, making it fast and easy to develop in. CF is a multi-paradigmed language, supporting classical OO and functional programming.
2
-
3
- CF also has a built in tag-based templating language that makes it ideal for web apps. It runs in a J2EE container with many bundled libraries that make it very productive without the need to install many packages. CF has native support zip files, PDF and Excel generation, E-mails, FTP, HTTP, S3 file systems, ESAPI security libraries, JDBC drivers, JSON data types and REST APIs.
4
-
5
- CF can also leverage any Java project by dropping the jars in project and directly instantiating Java objects in your code. You can learn more about basic syntax and first class data types in this guide: [Modern ColdFusion (CFML) in 100 Minutes](https://www.gitbook.com/book/ortus/modern-coldfusion-cfml-in-100-minutes/details)
6
-
1
+ ColdFusion (CFML) is a JVM scripting language whose syntax is similar to C or JavaScript.
2
+ It JIT compiles to byte code that runs on the JVM but is dynamic and loosely typed, making it fast and easy to develop in.
3
+ CF is a multi-paradigmed language, supporting classical OO and functional programming.
7
4
 
5
+ CFML also has a built-in tag-based templating language that makes it ideal for web apps.
6
+ It runs in a J2EE container with many bundled libraries that make it very productive without the need to install many packages.
7
+ CFML has native support for zip files, PDF and Excel generation, E-mails, FTP, HTTP, S3 file systems, ESAPI security libraries, JDBC drivers, JSON and REST APIs.
8
8
 
9
+ CFML can also leverage any Java project by dropping the jars in project and directly instantiating Java objects in your code.
10
+ You can learn more about basic syntax and first class data types in this guide: [Modern ColdFusion (CFML) in 100 Minutes](https://www.gitbook.com/book/ortus/modern-coldfusion-cfml-in-100-minutes/details)
@@ -82,6 +82,13 @@ An example of this is the [RunLengthEncoding](https://github.com/exercism/csharp
82
82
 
83
83
  Here the **Assert** is being overridden. The assert needs to call additional functions, but only if the property is `consistency`. Otherwise, render the assert as usual.
84
84
 
85
+ ### string[] RenderAdditionalMethods()
86
+ Allow additional methods to be added to the test suite.
87
+
88
+ There may exist cases where a suite of unit tests will need to reuse the same logic in each of the tests. Rather than duplicating code, this method allows you to provide helper methods for the tests.
89
+
90
+ Additional methods added using this override will be added to the bottom of the test suite.
91
+
85
92
  ## Updating Existing Files
86
93
  It is possible that an existing exercise does not match the canonical data. It is OK to update the exercise stub and/or the exercise example to follow the canonical data! An example might be that an exercise is named SumOfMultiples, but the SumOfMultiples.cs and Example.cs files both use `Multiples` as the name of the class.
87
94
 
@@ -253,104 +253,104 @@ public class ClockTest
253
253
  public void Clocks_with_same_time()
254
254
  {
255
255
  var sut = new Clock(15, 37);
256
- Assert.True(sut.Equals(new Clock(15, 37)));
256
+ Assert.Equal(new Clock(15, 37), sut);
257
257
  }
258
258
 
259
259
  [Fact(Skip = "Remove to run test")]
260
260
  public void Clocks_a_minute_apart()
261
261
  {
262
262
  var sut = new Clock(15, 36);
263
- Assert.False(sut.Equals(new Clock(15, 37)));
263
+ Assert.NotEqual(new Clock(15, 37), sut);
264
264
  }
265
265
 
266
266
  [Fact(Skip = "Remove to run test")]
267
267
  public void Clocks_an_hour_apart()
268
268
  {
269
269
  var sut = new Clock(14, 37);
270
- Assert.False(sut.Equals(new Clock(15, 37)));
270
+ Assert.NotEqual(new Clock(15, 37), sut);
271
271
  }
272
272
 
273
273
  [Fact(Skip = "Remove to run test")]
274
274
  public void Clocks_with_hour_overflow()
275
275
  {
276
276
  var sut = new Clock(10, 37);
277
- Assert.True(sut.Equals(new Clock(34, 37)));
277
+ Assert.Equal(new Clock(34, 37), sut);
278
278
  }
279
279
 
280
280
  [Fact(Skip = "Remove to run test")]
281
281
  public void Clocks_with_hour_overflow_by_several_days()
282
282
  {
283
283
  var sut = new Clock(3, 11);
284
- Assert.True(sut.Equals(new Clock(99, 11)));
284
+ Assert.Equal(new Clock(99, 11), sut);
285
285
  }
286
286
 
287
287
  [Fact(Skip = "Remove to run test")]
288
288
  public void Clocks_with_negative_hour()
289
289
  {
290
290
  var sut = new Clock(22, 40);
291
- Assert.True(sut.Equals(new Clock(-2, 40)));
291
+ Assert.Equal(new Clock(-2, 40), sut);
292
292
  }
293
293
 
294
294
  [Fact(Skip = "Remove to run test")]
295
295
  public void Clocks_with_negative_hour_that_wraps()
296
296
  {
297
297
  var sut = new Clock(17, 3);
298
- Assert.True(sut.Equals(new Clock(-31, 3)));
298
+ Assert.Equal(new Clock(-31, 3), sut);
299
299
  }
300
300
 
301
301
  [Fact(Skip = "Remove to run test")]
302
302
  public void Clocks_with_negative_hour_that_wraps_multiple_times()
303
303
  {
304
304
  var sut = new Clock(13, 49);
305
- Assert.True(sut.Equals(new Clock(-83, 49)));
305
+ Assert.Equal(new Clock(-83, 49), sut);
306
306
  }
307
307
 
308
308
  [Fact(Skip = "Remove to run test")]
309
309
  public void Clocks_with_minute_overflow()
310
310
  {
311
311
  var sut = new Clock(0, 1);
312
- Assert.True(sut.Equals(new Clock(0, 1441)));
312
+ Assert.Equal(new Clock(0, 1441), sut);
313
313
  }
314
314
 
315
315
  [Fact(Skip = "Remove to run test")]
316
316
  public void Clocks_with_minute_overflow_by_several_days()
317
317
  {
318
318
  var sut = new Clock(2, 2);
319
- Assert.True(sut.Equals(new Clock(2, 4322)));
319
+ Assert.Equal(new Clock(2, 4322), sut);
320
320
  }
321
321
 
322
322
  [Fact(Skip = "Remove to run test")]
323
323
  public void Clocks_with_negative_minute()
324
324
  {
325
325
  var sut = new Clock(2, 40);
326
- Assert.True(sut.Equals(new Clock(3, -20)));
326
+ Assert.Equal(new Clock(3, -20), sut);
327
327
  }
328
328
 
329
329
  [Fact(Skip = "Remove to run test")]
330
330
  public void Clocks_with_negative_minute_that_wraps()
331
331
  {
332
332
  var sut = new Clock(4, 10);
333
- Assert.True(sut.Equals(new Clock(5, -1490)));
333
+ Assert.Equal(new Clock(5, -1490), sut);
334
334
  }
335
335
 
336
336
  [Fact(Skip = "Remove to run test")]
337
337
  public void Clocks_with_negative_minute_that_wraps_multiple_times()
338
338
  {
339
339
  var sut = new Clock(6, 15);
340
- Assert.True(sut.Equals(new Clock(6, -4305)));
340
+ Assert.Equal(new Clock(6, -4305), sut);
341
341
  }
342
342
 
343
343
  [Fact(Skip = "Remove to run test")]
344
344
  public void Clocks_with_negative_hours_and_minutes()
345
345
  {
346
346
  var sut = new Clock(7, 32);
347
- Assert.True(sut.Equals(new Clock(-12, -268)));
347
+ Assert.Equal(new Clock(-12, -268), sut);
348
348
  }
349
349
 
350
350
  [Fact(Skip = "Remove to run test")]
351
351
  public void Clocks_with_negative_hours_and_minutes_that_wrap()
352
352
  {
353
353
  var sut = new Clock(18, 7);
354
- Assert.True(sut.Equals(new Clock(-54, -11513)));
354
+ Assert.Equal(new Clock(-54, -11513), sut);
355
355
  }
356
356
  }