trackler 2.2.1.52 → 2.2.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/leap/canonical-data.json +2 -2
- data/tracks/cfml/tasks/FormatConfig.cfc +6 -4
- data/tracks/cfml/tasks/GenerateReadme.cfc +197 -0
- data/tracks/cfml/tasks/ScaffoldExercise.cfc +6 -0
- data/tracks/csharp/config.json +1 -1
- data/tracks/delphi/exercises/leap/uLeapTests.pas +1 -1
- data/tracks/fsharp/exercises/clock/Clock.fs +1 -1
- data/tracks/fsharp/exercises/clock/ClockTest.fs +239 -61
- data/tracks/fsharp/exercises/clock/Example.fs +3 -3
- data/tracks/fsharp/exercises/dominoes/DominoesTest.fs +29 -26
- data/tracks/fsharp/exercises/largest-series-product/LargestSeriesProductTest.fs +30 -15
- data/tracks/fsharp/exercises/leap/LeapTest.fs +2 -2
- data/tracks/fsharp/exercises/rectangles/Example.fs +1 -1
- data/tracks/fsharp/exercises/rectangles/Rectangles.fs +1 -1
- data/tracks/fsharp/exercises/rectangles/RectanglesTest.fs +66 -43
- data/tracks/fsharp/generators/Generators.fs +85 -1
- data/tracks/java/scripts/canonical_data_check.sh +8 -0
- data/tracks/kotlin/.gitignore +1 -0
- data/tracks/kotlin/exercises/acronym/.meta/version +1 -0
- data/tracks/kotlin/exercises/acronym/src/test/kotlin/AcronymTest.kt +9 -10
- data/tracks/kotlin/exercises/all-your-base/.meta/version +1 -1
- data/tracks/kotlin/exercises/all-your-base/src/test/kotlin/BaseConverterTest.kt +20 -20
- data/tracks/kotlin/exercises/allergies/.meta/version +1 -0
- data/tracks/kotlin/exercises/allergies/src/test/kotlin/AllergiesTest.kt +19 -72
- data/tracks/kotlin/exercises/anagram/.meta/src/reference/kotlin/Anagram.kt +7 -4
- data/tracks/kotlin/exercises/anagram/.meta/version +1 -0
- data/tracks/kotlin/exercises/anagram/src/test/kotlin/AnagramTest.kt +76 -29
- data/tracks/kotlin/exercises/atbash-cipher/.meta/version +1 -0
- data/tracks/kotlin/exercises/atbash-cipher/src/test/kotlin/AtbashTest.kt +6 -3
- data/tracks/kotlin/exercises/beer-song/.meta/version +1 -0
- data/tracks/kotlin/exercises/beer-song/src/test/kotlin/BeerSongTest.kt +21 -46
- data/tracks/kotlin/exercises/binary-search/.meta/version +1 -0
- data/tracks/kotlin/exercises/binary-search/src/test/kotlin/BinarySearchTest.kt +30 -19
- data/tracks/kotlin/exercises/bob/.meta/src/reference/kotlin/Bob.kt +8 -7
- data/tracks/kotlin/exercises/bob/.meta/version +1 -0
- data/tracks/kotlin/exercises/bob/src/test/kotlin/BobTest.kt +57 -15
- data/tracks/kotlin/exercises/bracket-push/.meta/version +1 -0
- data/tracks/kotlin/exercises/bracket-push/src/test/kotlin/BracketPushTest.kt +3 -1
- data/tracks/kotlin/exercises/collatz-conjecture/.meta/version +1 -1
- data/tracks/kotlin/exercises/difference-of-squares/.meta/version +1 -0
- data/tracks/kotlin/exercises/difference-of-squares/src/test/kotlin/SquaresTest.kt +10 -23
- data/tracks/kotlin/exercises/etl/.meta/src/reference/kotlin/ETL.kt +7 -1
- data/tracks/kotlin/exercises/etl/.meta/version +1 -0
- data/tracks/kotlin/exercises/etl/src/test/kotlin/ETLTest.kt +10 -10
- data/tracks/kotlin/exercises/flatten-array/.meta/version +1 -0
- data/tracks/kotlin/exercises/flatten-array/src/test/kotlin/FlattenerTest.kt +8 -16
- data/tracks/kotlin/exercises/gigasecond/.meta/version +1 -0
- data/tracks/kotlin/exercises/gigasecond/src/test/kotlin/GigasecondTest.kt +1 -1
- data/tracks/kotlin/exercises/hamming/.meta/src/reference/kotlin/Hamming.kt +1 -1
- data/tracks/kotlin/exercises/hamming/.meta/version +1 -1
- data/tracks/kotlin/exercises/hamming/src/test/kotlin/HammingTest.kt +4 -4
- data/tracks/kotlin/exercises/hello-world/.meta/version +1 -0
- data/tracks/kotlin/exercises/hello-world/src/test/kotlin/HelloWorldTest.kt +1 -1
- data/tracks/kotlin/exercises/isogram/.meta/version +1 -0
- data/tracks/kotlin/exercises/isogram/src/test/kotlin/IsogramTest.kt +5 -8
- data/tracks/kotlin/exercises/largest-series-product/.meta/src/reference/kotlin/Series.kt +2 -3
- data/tracks/kotlin/exercises/largest-series-product/.meta/version +1 -0
- data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesTest.kt +97 -0
- data/tracks/kotlin/exercises/leap/.meta/version +1 -0
- data/tracks/kotlin/exercises/leap/src/test/kotlin/LeapTest.kt +8 -26
- data/tracks/kotlin/exercises/list-ops/.meta/version +1 -1
- data/tracks/kotlin/exercises/luhn/.meta/version +1 -0
- data/tracks/kotlin/exercises/luhn/src/test/kotlin/LuhnTest.kt +0 -3
- data/tracks/kotlin/exercises/nth-prime/.meta/version +1 -0
- data/tracks/kotlin/exercises/nth-prime/src/test/kotlin/PrimeTest.kt +0 -2
- data/tracks/kotlin/exercises/nucleotide-count/.meta/src/reference/kotlin/{DNA.kt → Dna.kt} +3 -8
- data/tracks/kotlin/exercises/nucleotide-count/.meta/version +1 -0
- data/tracks/kotlin/exercises/nucleotide-count/src/test/kotlin/DnaTest.kt +48 -0
- data/tracks/kotlin/exercises/pangram/.meta/src/reference/kotlin/{Pangrams.kt → Pangram.kt} +1 -1
- data/tracks/kotlin/exercises/pangram/.meta/version +1 -1
- data/tracks/kotlin/exercises/pangram/src/test/kotlin/PangramTest.kt +15 -9
- data/tracks/kotlin/exercises/pascals-triangle/.meta/version +1 -0
- data/tracks/kotlin/exercises/pascals-triangle/src/test/kotlin/PascalsTriangleTest.kt +32 -14
- data/tracks/kotlin/exercises/perfect-numbers/.meta/src/reference/kotlin/NaturalNumber.kt +1 -1
- data/tracks/kotlin/exercises/perfect-numbers/.meta/version +1 -0
- data/tracks/kotlin/exercises/perfect-numbers/src/test/kotlin/{PerfectNumbersTest.kt → NaturalNumberTest.kt} +25 -7
- data/tracks/kotlin/exercises/phone-number/.meta/src/reference/kotlin/PhoneNumber.kt +15 -7
- data/tracks/kotlin/exercises/phone-number/.meta/version +1 -0
- data/tracks/kotlin/exercises/phone-number/src/test/kotlin/PhoneNumberTest.kt +46 -29
- data/tracks/kotlin/exercises/pig-latin/.meta/src/reference/kotlin/PigLatin.kt +2 -2
- data/tracks/kotlin/exercises/pig-latin/.meta/version +1 -0
- data/tracks/kotlin/exercises/pig-latin/src/test/kotlin/PigLatinTest.kt +21 -10
- data/tracks/kotlin/exercises/raindrops/.meta/version +1 -0
- data/tracks/kotlin/exercises/raindrops/src/test/kotlin/RaindropsTest.kt +19 -26
- data/tracks/kotlin/exercises/react/.meta/version +1 -0
- data/tracks/kotlin/exercises/react/src/test/kotlin/ReactTest.kt +11 -4
- data/tracks/kotlin/exercises/robot-simulator/.meta/version +1 -1
- data/tracks/kotlin/exercises/roman-numerals/.meta/version +1 -0
- data/tracks/kotlin/exercises/roman-numerals/src/test/kotlin/RomanNumeralTest.kt +1 -2
- data/tracks/kotlin/exercises/rotational-cipher/.meta/version +1 -1
- data/tracks/kotlin/exercises/rotational-cipher/src/test/kotlin/RotationalCipherTest.kt +7 -7
- data/tracks/kotlin/exercises/scrabble-score/.meta/src/reference/kotlin/{Scrabble.kt → ScrabbleScore.kt} +1 -1
- data/tracks/kotlin/exercises/scrabble-score/.meta/version +1 -0
- data/tracks/kotlin/exercises/scrabble-score/src/test/kotlin/ScrabbleScoreTest.kt +9 -7
- data/tracks/kotlin/exercises/sieve/.meta/version +1 -0
- data/tracks/kotlin/exercises/sieve/src/test/kotlin/SieveTest.kt +8 -0
- data/tracks/kotlin/exercises/space-age/.meta/version +1 -0
- data/tracks/kotlin/exercises/space-age/src/test/kotlin/SpaceAgeTest.kt +1 -16
- data/tracks/kotlin/exercises/sum-of-multiples/.meta/version +1 -0
- data/tracks/kotlin/exercises/sum-of-multiples/src/test/kotlin/SumOfMultiplesTest.kt +7 -7
- data/tracks/kotlin/exercises/triangle/.meta/version +1 -0
- data/tracks/kotlin/exercises/two-fer/.meta/version +1 -0
- data/tracks/kotlin/exercises/two-fer/src/test/kotlin/TwoferTest.kt +0 -1
- data/tracks/kotlin/exercises/word-count/.meta/src/reference/kotlin/WordCount.kt +6 -2
- data/tracks/kotlin/exercises/word-count/.meta/version +1 -0
- data/tracks/kotlin/exercises/word-count/src/test/kotlin/WordCountTest.kt +31 -9
- data/tracks/kotlin/scripts/canonical_data_check.sh +8 -0
- data/tracks/perl6/exercises/leap/leap.t +2 -2
- data/tracks/php/config.json +16 -0
- data/tracks/php/exercises/crypto-square/crypto-square_test.php +50 -0
- data/tracks/php/exercises/crypto-square/example.php +32 -0
- data/tracks/php/exercises/meetup/README.md +21 -0
- data/tracks/php/exercises/meetup/example.php +19 -0
- data/tracks/php/exercises/meetup/meetup_test.php +577 -0
- data/tracks/python/README.md +7 -5
- data/tracks/python/config.json +36 -27
- data/tracks/python/docs/TESTS.md +36 -12
- data/tracks/python/exercises/complex-numbers/complex_numbers_test.py +1 -1
- data/tracks/python/exercises/diffie-hellman/.meta/hints.md +16 -0
- data/tracks/python/exercises/diffie-hellman/README.md +15 -2
- data/tracks/python/exercises/error-handling/README.md +23 -0
- data/tracks/python/exercises/error-handling/error_handling.py +14 -0
- data/tracks/python/exercises/error-handling/error_handling_test.py +66 -0
- data/tracks/python/exercises/error-handling/example.py +21 -0
- data/tracks/python/exercises/forth/forth_test.py +1 -1
- data/tracks/python/exercises/isogram/isogram_test.py +5 -3
- data/tracks/python/exercises/leap/leap_test.py +2 -2
- data/tracks/python/exercises/rotational-cipher/rotational_cipher_test.py +4 -4
- data/tracks/python/exercises/simple-cipher/.meta/hints.md +16 -0
- data/tracks/python/exercises/simple-cipher/README.md +17 -0
- data/tracks/python/exercises/sum-of-multiples/sum_of_multiples_test.py +4 -1
- data/tracks/python/exercises/twelve-days/example.py +3 -3
- data/tracks/python/exercises/twelve-days/twelve_days.py +2 -2
- metadata +53 -9
- data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesInvalidInputTest.kt +0 -30
- data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesValidInputTest.kt +0 -34
- data/tracks/kotlin/exercises/nucleotide-count/src/test/kotlin/NucleotideTest.kt +0 -87
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 95152d34553c950841be6dbe52afef273a56ab43
|
|
4
|
+
data.tar.gz: 4d2c405d864d1c9fef3295f2cc30b316fdbc30f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ebdadfa92b814621a979f0dbdb8060f3d1a952e000a93cea60b4a71cef0435ca67723bfd2ec5f8ad109acd826b3024d7890283cbad44f2fda01e065f8f6b805b
|
|
7
|
+
data.tar.gz: d8fa0417ab4cc2173f02b5fa5aa90975d5b62cdc8a2c1f8d965fbdfe458b05371273ad47ffb337eb3855d4a331f33a873568a3197513e05480e285c09ef2ee9b
|
data/lib/trackler/version.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"exercise": "leap",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"cases": [
|
|
5
5
|
{
|
|
6
6
|
"description": "year not divisible by 4: common year",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
{
|
|
12
12
|
"description": "year divisible by 4, not divisible by 100: leap year",
|
|
13
13
|
"property": "leapYear",
|
|
14
|
-
"input":
|
|
14
|
+
"input": 1996,
|
|
15
15
|
"expected": true
|
|
16
16
|
},
|
|
17
17
|
{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* This is a simple task runner that formats the JSON config file. This should only be neccessary if
|
|
2
|
+
* This is a simple task runner that formats the JSON config file. This should only be neccessary if you've edited it by
|
|
3
3
|
* hand and want to get it back into the proper format as far as spacing and indentation goes. This follows the same format as `configlet fmt`
|
|
4
4
|
*/
|
|
5
5
|
component {
|
|
@@ -9,17 +9,19 @@ component {
|
|
|
9
9
|
var repoRootPath = expandPath( getDirectoryFromPath( getCurrentTemplatePath() ) & '../' );
|
|
10
10
|
// Read in the current JSON config file
|
|
11
11
|
var configJSONRaw = fileRead( repoRootPath & '/config.json' );
|
|
12
|
-
var configJSON = deserializeJSON( configJSONRaw );
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
// Format JSON file to spec
|
|
14
|
+
var newConfigJSONRaw = formatterUtil.formatJSON( json=configJSONRaw, indent=' ' , lineEnding=chr( 10 ), spaceAfterColon=true );
|
|
15
15
|
|
|
16
|
+
// Only save if it's different to avoid touching the file needlessly
|
|
16
17
|
if( newConfigJSONRaw != configJSONRaw ) {
|
|
18
|
+
|
|
17
19
|
// Write it back out with the proper formatting styles applied
|
|
18
20
|
fileWrite( repoRootPath & '/config.json', newConfigJSONRaw );
|
|
19
21
|
|
|
20
22
|
print.greenLine( 'Config file [#repoRootPath#config.json] formatted!' );
|
|
21
23
|
} else {
|
|
22
|
-
print.whiteLine( 'Config file [#repoRootPath#config.json] is already formatted!' );
|
|
24
|
+
print.whiteLine( 'Config file [#repoRootPath#config.json] is already formatted! No Chanages needed.' );
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate README.md files for exercises
|
|
3
|
+
*/
|
|
4
|
+
component {
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Run the task to generate read me files
|
|
8
|
+
*/
|
|
9
|
+
function run(
|
|
10
|
+
slug,
|
|
11
|
+
boolean all=false,
|
|
12
|
+
boolean force=false
|
|
13
|
+
){
|
|
14
|
+
|
|
15
|
+
/* Init global variables */
|
|
16
|
+
repoRootPath = expandPath( getDirectoryFromPath( getCurrentTemplatePath() ) & '../' );
|
|
17
|
+
problemSpecsPath = expandPath( getDirectoryFromPath( getCurrentTemplatePath() ) & '../../problem-specifications' );
|
|
18
|
+
trackReadmeInsert= fileRead( repoRootPath & "docs/EXERCISE_README_INSERT.md" );
|
|
19
|
+
overwriteExistingFiles = arguments.force;
|
|
20
|
+
|
|
21
|
+
if( !directoryExists( problemSpecsPath ) ){
|
|
22
|
+
error( 'Cannot find [problem-specifications] repo. It needs to be git cloned to [#problemSpecsPath#]' );
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if( all ) {
|
|
26
|
+
|
|
27
|
+
// Get an array of all the excercise names
|
|
28
|
+
var exercises = directoryList( expandPath( getDirectoryFromPath( getCurrentTemplatePath() ) & '../exercises' ) )
|
|
29
|
+
.map( function( path ) {
|
|
30
|
+
return path.listLast( '/\' );
|
|
31
|
+
} );
|
|
32
|
+
|
|
33
|
+
} else {
|
|
34
|
+
|
|
35
|
+
// Acquire slug
|
|
36
|
+
if( isNull( arguments.slug ) ) {
|
|
37
|
+
arguments.slug = ask( 'Exercise slug as defined by Excercism. Ex: "hello-world": ' );
|
|
38
|
+
}
|
|
39
|
+
var exercises = [ slug ];
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
exercises.each( function( slug ) {
|
|
44
|
+
|
|
45
|
+
generateReadme( arguments.slug );
|
|
46
|
+
|
|
47
|
+
} ); // End exercises.each()
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private function generateReadme( required string slug ) {
|
|
52
|
+
|
|
53
|
+
var readmeContent = "";
|
|
54
|
+
var readMeFile = repoRootPath & "/exercises/" & arguments.slug & "/README.md";
|
|
55
|
+
|
|
56
|
+
if ( !fileExists(readMeFile) || overwriteExistingFiles) {
|
|
57
|
+
|
|
58
|
+
var spec = getSpec( arguments.slug );
|
|
59
|
+
|
|
60
|
+
readmeContent = "## #spec.name#" & chr( 10 ) & chr( 10 );
|
|
61
|
+
readmeContent = readmeContent & spec.description & chr( 10 );
|
|
62
|
+
readmeContent = readmeContent & getHints( arguments.slug ) & chr( 10 );
|
|
63
|
+
readmeContent = readmeContent & trackReadmeInsert & chr( 10 );
|
|
64
|
+
readmeContent = readmeContent & spec.credits & chr( 10 );
|
|
65
|
+
readmeContent = readmeContent & "#### Submitting Incomplete Solutions#chr( 10 )#It's possible to submit an incomplete solution so you can see how others have completed the exercise.#chr( 10 )#";
|
|
66
|
+
|
|
67
|
+
/* Write the file */
|
|
68
|
+
fileWrite( readMeFile , readmeContent );
|
|
69
|
+
|
|
70
|
+
print.greenLine( 'Readme generated!' )
|
|
71
|
+
.indentedYellowLine( readMeFile )
|
|
72
|
+
.toConsole();
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
print.redLine("README.md already exists! Use the overwrite=true to overwrite the file.")
|
|
76
|
+
.indentedYellowLine( readMeFile )
|
|
77
|
+
.toConsole();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
* Get the optional .meta/hint.md content
|
|
85
|
+
*
|
|
86
|
+
*/
|
|
87
|
+
private function getHints( required string slug ) {
|
|
88
|
+
|
|
89
|
+
var hintsFilePath = repoRootPath & "/exercises/" & arguments.slug & "/.meta/hints.md";
|
|
90
|
+
var hints = fileExists( hintsFilePath ) ? fileRead( hintsFilePath ) : "";
|
|
91
|
+
|
|
92
|
+
return hints;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private function getSpec( required string slug ) {
|
|
96
|
+
|
|
97
|
+
var spec = getExerciseMetadata( arguments.slug );
|
|
98
|
+
|
|
99
|
+
/* Use title from metadata.yml if provided else we must use the slug */
|
|
100
|
+
if ( len( spec.title )) {
|
|
101
|
+
spec.name = spec.title;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
spec.name = titleCaseSlug( arguments.slug );
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
spec.credits = getCredits( spec );
|
|
108
|
+
spec.description = getDescription( arguments.slug );
|
|
109
|
+
|
|
110
|
+
return spec;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
*
|
|
115
|
+
* Get the exercise description
|
|
116
|
+
*
|
|
117
|
+
*/
|
|
118
|
+
private function getDescription( required string slug ) {
|
|
119
|
+
|
|
120
|
+
var descriptionFilePath = problemSpecsPath & "/exercises/" & arguments.slug & "/description.md";
|
|
121
|
+
|
|
122
|
+
return fileExists( descriptionFilePath ) ? trim( fileRead( descriptionFilePath ) ) : "";
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
*
|
|
127
|
+
* Get the content for exercise credits
|
|
128
|
+
*
|
|
129
|
+
*/
|
|
130
|
+
private function getCredits( required struct spec ) {
|
|
131
|
+
|
|
132
|
+
if ( spec.source_url == "" ) {
|
|
133
|
+
var credits = spec.source;
|
|
134
|
+
}
|
|
135
|
+
else if ( spec.source == "") {
|
|
136
|
+
var credits = "[#spec.source_url#](#spec.source_url#)";
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
var credits = "#spec.source# [#spec.source_url#](#spec.source_url#)";
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if ( len( credits ) ) {
|
|
143
|
+
credits = "#### Source" & chr( 10 ) & chr( 10 ) & credits & chr( 10 );
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return credits;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
*
|
|
151
|
+
* Convert exercise slug to a title
|
|
152
|
+
*
|
|
153
|
+
*/
|
|
154
|
+
private function titleCaseSlug( required string slug ) {
|
|
155
|
+
return trim( reReplace( arguments.slug, "(\b|-)([a-zA-Z])", " \u\2", "all" ) );
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
*
|
|
160
|
+
* Get exercise metadata from metadata.yml in the problem-specifications
|
|
161
|
+
*
|
|
162
|
+
*/
|
|
163
|
+
private struct function getExerciseMetadata( required string slug ) {
|
|
164
|
+
|
|
165
|
+
var metadataFilePath = problemSpecsPath & "/exercises/" & arguments.slug & "/metadata.yml";
|
|
166
|
+
var content = fileRead(metadataFilePath);
|
|
167
|
+
var metadata = {};
|
|
168
|
+
|
|
169
|
+
/* Get the title if provided in metadata.yml */
|
|
170
|
+
metadata.title = parseMetadata( "title", content );
|
|
171
|
+
|
|
172
|
+
/* Get the source of the exercise if provided in metadata.yml */
|
|
173
|
+
metadata.source = parseMetadata( "source", content );
|
|
174
|
+
|
|
175
|
+
/* Get the source url if provided in metadata.yml */
|
|
176
|
+
metadata.source_url = parseMetadata( "source_url", content );
|
|
177
|
+
|
|
178
|
+
return metadata;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
*
|
|
183
|
+
* Parse metadata from metadata.yml content
|
|
184
|
+
*
|
|
185
|
+
*/
|
|
186
|
+
private string function parseMetadata( required string key, required string content ) {
|
|
187
|
+
var result = "";
|
|
188
|
+
|
|
189
|
+
var matches = reFindNoCase( "#arguments.key#: ""(.*?)""", content, 1, true );
|
|
190
|
+
if ( matches.pos.len() == 2 ) {
|
|
191
|
+
result = mid( content, matches.pos[2], matches.len[2]);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
}
|
|
@@ -79,6 +79,12 @@ component {
|
|
|
79
79
|
.params( 'GenerateTests', 'run', slug )
|
|
80
80
|
.inWorkingDirectory( repoRootPath & '/tasks' )
|
|
81
81
|
.run();
|
|
82
|
+
|
|
83
|
+
// Generate README.md
|
|
84
|
+
command( 'task run' )
|
|
85
|
+
.params( 'GenerateReadme', 'run', slug )
|
|
86
|
+
.inWorkingDirectory( repoRootPath & '/tasks' )
|
|
87
|
+
.run();
|
|
82
88
|
|
|
83
89
|
}
|
|
84
90
|
|
data/tracks/csharp/config.json
CHANGED
|
@@ -36,7 +36,7 @@ end;
|
|
|
36
36
|
|
|
37
37
|
procedure YearTest.year_divisible_by_4_not_divisible_by_100_leap_year;
|
|
38
38
|
begin
|
|
39
|
-
assert.IsTrue(TYear.IsLeap(
|
|
39
|
+
assert.IsTrue(TYear.IsLeap(1996), 'Expected ''true'', 1996 is a leap year.');
|
|
40
40
|
end;
|
|
41
41
|
|
|
42
42
|
procedure YearTest.year_divisible_by_100_not_divisible_by_400_common_year;
|
|
@@ -1,96 +1,274 @@
|
|
|
1
|
+
// This file was auto-generated based on version 1.0.1 of the canonical data.
|
|
2
|
+
|
|
1
3
|
module ClockTest
|
|
2
4
|
|
|
3
|
-
open System
|
|
4
|
-
open Xunit
|
|
5
5
|
open FsUnit.Xunit
|
|
6
|
+
open Xunit
|
|
7
|
+
|
|
6
8
|
open Clock
|
|
7
9
|
|
|
8
10
|
[<Fact>]
|
|
9
|
-
let ``
|
|
10
|
-
let clock =
|
|
11
|
+
let ``On the hour`` () =
|
|
12
|
+
let clock = create 8 0
|
|
11
13
|
display clock |> should equal "08:00"
|
|
12
14
|
|
|
13
|
-
[<Fact(Skip = "Remove to run test")>]
|
|
14
|
-
let ``
|
|
15
|
-
let clock =
|
|
16
|
-
display clock |> should equal "09:00"
|
|
17
|
-
|
|
18
|
-
[<Fact(Skip = "Remove to run test")>]
|
|
19
|
-
let ``Can print single-digit minutes`` () =
|
|
20
|
-
let clock = mkClock 11 9
|
|
15
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
16
|
+
let ``Past the hour`` () =
|
|
17
|
+
let clock = create 11 9
|
|
21
18
|
display clock |> should equal "11:09"
|
|
22
19
|
|
|
23
20
|
[<Fact(Skip = "Remove to run test")>]
|
|
24
|
-
let ``
|
|
25
|
-
let clock =
|
|
26
|
-
display clock |> should equal "
|
|
21
|
+
let ``Midnight is zero hours`` () =
|
|
22
|
+
let clock = create 24 0
|
|
23
|
+
display clock |> should equal "00:00"
|
|
27
24
|
|
|
28
25
|
[<Fact(Skip = "Remove to run test")>]
|
|
29
|
-
let ``
|
|
30
|
-
let clock =
|
|
31
|
-
|
|
32
|
-
display added |> should equal "10:03"
|
|
26
|
+
let ``Hour rolls over`` () =
|
|
27
|
+
let clock = create 25 0
|
|
28
|
+
display clock |> should equal "01:00"
|
|
33
29
|
|
|
34
30
|
[<Fact(Skip = "Remove to run test")>]
|
|
35
|
-
let ``
|
|
36
|
-
let clock =
|
|
37
|
-
|
|
38
|
-
display added |> should equal "11:03"
|
|
31
|
+
let ``Hour rolls over continuously`` () =
|
|
32
|
+
let clock = create 100 0
|
|
33
|
+
display clock |> should equal "04:00"
|
|
39
34
|
|
|
40
35
|
[<Fact(Skip = "Remove to run test")>]
|
|
41
|
-
let ``
|
|
42
|
-
let clock =
|
|
43
|
-
|
|
44
|
-
display added |> should equal "10:24"
|
|
36
|
+
let ``Sixty minutes is next hour`` () =
|
|
37
|
+
let clock = create 1 60
|
|
38
|
+
display clock |> should equal "02:00"
|
|
45
39
|
|
|
46
40
|
[<Fact(Skip = "Remove to run test")>]
|
|
47
|
-
let ``
|
|
48
|
-
let clock =
|
|
49
|
-
|
|
50
|
-
display subtracted |> should equal "10:00"
|
|
41
|
+
let ``Minutes roll over`` () =
|
|
42
|
+
let clock = create 0 160
|
|
43
|
+
display clock |> should equal "02:40"
|
|
51
44
|
|
|
52
45
|
[<Fact(Skip = "Remove to run test")>]
|
|
53
|
-
let ``
|
|
54
|
-
let clock =
|
|
55
|
-
|
|
56
|
-
display subtracted |> should equal "09:33"
|
|
46
|
+
let ``Minutes roll over continuously`` () =
|
|
47
|
+
let clock = create 0 1723
|
|
48
|
+
display clock |> should equal "04:43"
|
|
57
49
|
|
|
58
50
|
[<Fact(Skip = "Remove to run test")>]
|
|
59
|
-
let ``
|
|
60
|
-
let clock =
|
|
61
|
-
|
|
62
|
-
display subtracted |> should equal "08:53"
|
|
51
|
+
let ``Hour and minutes roll over`` () =
|
|
52
|
+
let clock = create 25 160
|
|
53
|
+
display clock |> should equal "03:40"
|
|
63
54
|
|
|
64
55
|
[<Fact(Skip = "Remove to run test")>]
|
|
65
|
-
let ``
|
|
66
|
-
let clock =
|
|
67
|
-
|
|
68
|
-
display added |> should equal "00:01"
|
|
56
|
+
let ``Hour and minutes roll over continuously`` () =
|
|
57
|
+
let clock = create 201 3001
|
|
58
|
+
display clock |> should equal "11:01"
|
|
69
59
|
|
|
70
60
|
[<Fact(Skip = "Remove to run test")>]
|
|
71
|
-
let ``
|
|
72
|
-
let clock =
|
|
73
|
-
|
|
74
|
-
display subtracted |> should equal "23:59"
|
|
61
|
+
let ``Hour and minutes roll over to exactly midnight`` () =
|
|
62
|
+
let clock = create 72 8640
|
|
63
|
+
display clock |> should equal "00:00"
|
|
75
64
|
|
|
76
65
|
[<Fact(Skip = "Remove to run test")>]
|
|
77
|
-
let ``
|
|
78
|
-
let clock =
|
|
79
|
-
display clock |> should equal "
|
|
66
|
+
let ``Negative hour`` () =
|
|
67
|
+
let clock = create -1 15
|
|
68
|
+
display clock |> should equal "23:15"
|
|
80
69
|
|
|
81
70
|
[<Fact(Skip = "Remove to run test")>]
|
|
82
|
-
let ``
|
|
83
|
-
let clock =
|
|
84
|
-
display clock |> should equal "
|
|
71
|
+
let ``Negative hour rolls over`` () =
|
|
72
|
+
let clock = create -25 0
|
|
73
|
+
display clock |> should equal "23:00"
|
|
74
|
+
|
|
75
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
76
|
+
let ``Negative hour rolls over continuously`` () =
|
|
77
|
+
let clock = create -91 0
|
|
78
|
+
display clock |> should equal "05:00"
|
|
79
|
+
|
|
80
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
81
|
+
let ``Negative minutes`` () =
|
|
82
|
+
let clock = create 1 -40
|
|
83
|
+
display clock |> should equal "00:20"
|
|
84
|
+
|
|
85
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
86
|
+
let ``Negative minutes roll over`` () =
|
|
87
|
+
let clock = create 1 -160
|
|
88
|
+
display clock |> should equal "22:20"
|
|
89
|
+
|
|
90
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
91
|
+
let ``Negative minutes roll over continuously`` () =
|
|
92
|
+
let clock = create 1 -4820
|
|
93
|
+
display clock |> should equal "16:40"
|
|
94
|
+
|
|
95
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
96
|
+
let ``Negative hour and minutes both roll over`` () =
|
|
97
|
+
let clock = create -25 -160
|
|
98
|
+
display clock |> should equal "20:20"
|
|
99
|
+
|
|
100
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
101
|
+
let ``Negative hour and minutes both roll over continuously`` () =
|
|
102
|
+
let clock = create -121 -5810
|
|
103
|
+
display clock |> should equal "22:10"
|
|
104
|
+
|
|
105
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
106
|
+
let ``Add minutes`` () =
|
|
107
|
+
let clock = create 10 0
|
|
108
|
+
add 3 clock |> display |> should equal "10:03"
|
|
109
|
+
|
|
110
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
111
|
+
let ``Add no minutes`` () =
|
|
112
|
+
let clock = create 6 41
|
|
113
|
+
add 0 clock |> display |> should equal "06:41"
|
|
114
|
+
|
|
115
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
116
|
+
let ``Add to next hour`` () =
|
|
117
|
+
let clock = create 0 45
|
|
118
|
+
add 40 clock |> display |> should equal "01:25"
|
|
119
|
+
|
|
120
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
121
|
+
let ``Add more than one hour`` () =
|
|
122
|
+
let clock = create 10 0
|
|
123
|
+
add 61 clock |> display |> should equal "11:01"
|
|
124
|
+
|
|
125
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
126
|
+
let ``Add more than two hours with carry`` () =
|
|
127
|
+
let clock = create 0 45
|
|
128
|
+
add 160 clock |> display |> should equal "03:25"
|
|
129
|
+
|
|
130
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
131
|
+
let ``Add across midnight`` () =
|
|
132
|
+
let clock = create 23 59
|
|
133
|
+
add 2 clock |> display |> should equal "00:01"
|
|
134
|
+
|
|
135
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
136
|
+
let ``Add more than one day (1500 min = 25 hrs)`` () =
|
|
137
|
+
let clock = create 5 32
|
|
138
|
+
add 1500 clock |> display |> should equal "06:32"
|
|
139
|
+
|
|
140
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
141
|
+
let ``Add more than two days`` () =
|
|
142
|
+
let clock = create 1 1
|
|
143
|
+
add 3500 clock |> display |> should equal "11:21"
|
|
144
|
+
|
|
145
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
146
|
+
let ``Subtract minutes`` () =
|
|
147
|
+
let clock = create 10 3
|
|
148
|
+
add -3 clock |> display |> should equal "10:00"
|
|
149
|
+
|
|
150
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
151
|
+
let ``Subtract to previous hour`` () =
|
|
152
|
+
let clock = create 10 3
|
|
153
|
+
add -30 clock |> display |> should equal "09:33"
|
|
154
|
+
|
|
155
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
156
|
+
let ``Subtract more than an hour`` () =
|
|
157
|
+
let clock = create 10 3
|
|
158
|
+
add -70 clock |> display |> should equal "08:53"
|
|
159
|
+
|
|
160
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
161
|
+
let ``Subtract across midnight`` () =
|
|
162
|
+
let clock = create 0 3
|
|
163
|
+
add -4 clock |> display |> should equal "23:59"
|
|
164
|
+
|
|
165
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
166
|
+
let ``Subtract more than two hours`` () =
|
|
167
|
+
let clock = create 0 0
|
|
168
|
+
add -160 clock |> display |> should equal "21:20"
|
|
169
|
+
|
|
170
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
171
|
+
let ``Subtract more than two hours with borrow`` () =
|
|
172
|
+
let clock = create 6 15
|
|
173
|
+
add -160 clock |> display |> should equal "03:35"
|
|
174
|
+
|
|
175
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
176
|
+
let ``Subtract more than one day (1500 min = 25 hrs)`` () =
|
|
177
|
+
let clock = create 5 32
|
|
178
|
+
add -1500 clock |> display |> should equal "04:32"
|
|
179
|
+
|
|
180
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
181
|
+
let ``Subtract more than two days`` () =
|
|
182
|
+
let clock = create 2 20
|
|
183
|
+
add -3000 clock |> display |> should equal "00:20"
|
|
184
|
+
|
|
185
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
186
|
+
let ``Clocks with same time`` () =
|
|
187
|
+
let clock1 = create 15 37
|
|
188
|
+
let clock2 = create 15 37
|
|
189
|
+
clock1 = clock2 |> should equal true
|
|
190
|
+
|
|
191
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
192
|
+
let ``Clocks a minute apart`` () =
|
|
193
|
+
let clock1 = create 15 36
|
|
194
|
+
let clock2 = create 15 37
|
|
195
|
+
clock1 = clock2 |> should equal false
|
|
196
|
+
|
|
197
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
198
|
+
let ``Clocks an hour apart`` () =
|
|
199
|
+
let clock1 = create 14 37
|
|
200
|
+
let clock2 = create 15 37
|
|
201
|
+
clock1 = clock2 |> should equal false
|
|
85
202
|
|
|
86
203
|
[<Fact(Skip = "Remove to run test")>]
|
|
87
|
-
let ``Clocks with
|
|
88
|
-
let clock1 =
|
|
89
|
-
let clock2 =
|
|
90
|
-
clock1 |> should equal
|
|
204
|
+
let ``Clocks with hour overflow`` () =
|
|
205
|
+
let clock1 = create 10 37
|
|
206
|
+
let clock2 = create 34 37
|
|
207
|
+
clock1 = clock2 |> should equal true
|
|
91
208
|
|
|
92
209
|
[<Fact(Skip = "Remove to run test")>]
|
|
93
|
-
let ``
|
|
94
|
-
let clock1 =
|
|
95
|
-
let clock2 =
|
|
96
|
-
clock1 |> should equal
|
|
210
|
+
let ``Clocks with hour overflow by several days`` () =
|
|
211
|
+
let clock1 = create 3 11
|
|
212
|
+
let clock2 = create 99 11
|
|
213
|
+
clock1 = clock2 |> should equal true
|
|
214
|
+
|
|
215
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
216
|
+
let ``Clocks with negative hour`` () =
|
|
217
|
+
let clock1 = create 22 40
|
|
218
|
+
let clock2 = create -2 40
|
|
219
|
+
clock1 = clock2 |> should equal true
|
|
220
|
+
|
|
221
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
222
|
+
let ``Clocks with negative hour that wraps`` () =
|
|
223
|
+
let clock1 = create 17 3
|
|
224
|
+
let clock2 = create -31 3
|
|
225
|
+
clock1 = clock2 |> should equal true
|
|
226
|
+
|
|
227
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
228
|
+
let ``Clocks with negative hour that wraps multiple times`` () =
|
|
229
|
+
let clock1 = create 13 49
|
|
230
|
+
let clock2 = create -83 49
|
|
231
|
+
clock1 = clock2 |> should equal true
|
|
232
|
+
|
|
233
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
234
|
+
let ``Clocks with minute overflow`` () =
|
|
235
|
+
let clock1 = create 0 1
|
|
236
|
+
let clock2 = create 0 1441
|
|
237
|
+
clock1 = clock2 |> should equal true
|
|
238
|
+
|
|
239
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
240
|
+
let ``Clocks with minute overflow by several days`` () =
|
|
241
|
+
let clock1 = create 2 2
|
|
242
|
+
let clock2 = create 2 4322
|
|
243
|
+
clock1 = clock2 |> should equal true
|
|
244
|
+
|
|
245
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
246
|
+
let ``Clocks with negative minute`` () =
|
|
247
|
+
let clock1 = create 2 40
|
|
248
|
+
let clock2 = create 3 -20
|
|
249
|
+
clock1 = clock2 |> should equal true
|
|
250
|
+
|
|
251
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
252
|
+
let ``Clocks with negative minute that wraps`` () =
|
|
253
|
+
let clock1 = create 4 10
|
|
254
|
+
let clock2 = create 5 -1490
|
|
255
|
+
clock1 = clock2 |> should equal true
|
|
256
|
+
|
|
257
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
258
|
+
let ``Clocks with negative minute that wraps multiple times`` () =
|
|
259
|
+
let clock1 = create 6 15
|
|
260
|
+
let clock2 = create 6 -4305
|
|
261
|
+
clock1 = clock2 |> should equal true
|
|
262
|
+
|
|
263
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
264
|
+
let ``Clocks with negative hours and minutes`` () =
|
|
265
|
+
let clock1 = create 7 32
|
|
266
|
+
let clock2 = create -12 -268
|
|
267
|
+
clock1 = clock2 |> should equal true
|
|
268
|
+
|
|
269
|
+
[<Fact(Skip = "Remove to run test")>]
|
|
270
|
+
let ``Clocks with negative hours and minutes that wrap`` () =
|
|
271
|
+
let clock1 = create 18 7
|
|
272
|
+
let clock2 = create -54 -11513
|
|
273
|
+
clock1 = clock2 |> should equal true
|
|
274
|
+
|