From 4fc3868e16cd07c15d6e6abbe90113cfd8a933dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:25:42 -0800 Subject: [PATCH 1/2] add darts exercise --- config.json | 12 +- .../practice/darts/.docs/instructions.md | 31 ++++++ exercises/practice/darts/.meta/Example.cfc | 27 +++++ .../practice/darts/.meta/ExampleTest.cfc | 7 ++ exercises/practice/darts/.meta/config.json | 19 ++++ exercises/practice/darts/.meta/tests.toml | 49 +++++++++ exercises/practice/darts/Darts.cfc | 13 +++ exercises/practice/darts/DartsTest.cfc | 67 ++++++++++++ exercises/practice/darts/TestRunner.cfc | 103 ++++++++++++++++++ exercises/practice/darts/box.json | 8 ++ exercises/practice/darts/index.cfm | 37 +++++++ 11 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 exercises/practice/darts/.docs/instructions.md create mode 100644 exercises/practice/darts/.meta/Example.cfc create mode 100644 exercises/practice/darts/.meta/ExampleTest.cfc create mode 100644 exercises/practice/darts/.meta/config.json create mode 100644 exercises/practice/darts/.meta/tests.toml create mode 100644 exercises/practice/darts/Darts.cfc create mode 100644 exercises/practice/darts/DartsTest.cfc create mode 100644 exercises/practice/darts/TestRunner.cfc create mode 100644 exercises/practice/darts/box.json create mode 100644 exercises/practice/darts/index.cfm diff --git a/config.json b/config.json index e86d5ee..18211d3 100644 --- a/config.json +++ b/config.json @@ -312,6 +312,14 @@ "prerequisites": [], "difficulty": 1, "topics": null + }, + { + "slug": "darts", + "name": "Darts", + "uuid": "85636c8c-55f6-4890-a6a6-5cbffcbbdd4c", + "practices": [], + "prerequisites": [], + "difficulty": 2 } ] }, @@ -347,7 +355,7 @@ "content": "Easily access databases, natively convert HTML to PDF, parse XML, spin up APIs, or write to S3.", "icon": "cross-platform" } - ], + ], "tags": [ "paradigm/declarative", "typing/dynamic", @@ -358,4 +366,4 @@ "used_for/frontends", "used_for/web_development" ] -} +} \ No newline at end of file diff --git a/exercises/practice/darts/.docs/instructions.md b/exercises/practice/darts/.docs/instructions.md new file mode 100644 index 0000000..5e57a86 --- /dev/null +++ b/exercises/practice/darts/.docs/instructions.md @@ -0,0 +1,31 @@ +# Instructions + +Write a function that returns the earned points in a single toss of a Darts game. + +[Darts][darts] is a game where players throw darts at a [target][darts-target]. + +In our particular instance of the game, the target rewards 4 different amounts of points, depending on where the dart lands: + +![Our dart scoreboard with values from a complete miss to a bullseye](https://assets.exercism.org/images/exercises/darts/darts-scoreboard.svg) + +- If the dart lands outside the target, player earns no points (0 points). +- If the dart lands in the outer circle of the target, player earns 1 point. +- If the dart lands in the middle circle of the target, player earns 5 points. +- If the dart lands in the inner circle of the target, player earns 10 points. + +The outer circle has a radius of 10 units (this is equivalent to the total radius for the entire target), the middle circle a radius of 5 units, and the inner circle a radius of 1. +Of course, they are all centered at the same point — that is, the circles are [concentric][] defined by the coordinates (0, 0). + +Write a function that given a point in the target (defined by its [Cartesian coordinates][cartesian-coordinates] `x` and `y`, where `x` and `y` are [real][real-numbers]), returns the correct amount earned by a dart landing at that point. + +## Credit + +The scoreboard image was created by [habere-et-dispertire][habere-et-dispertire] using [Inkscape][inkscape]. + +[darts]: https://en.wikipedia.org/wiki/Darts +[darts-target]: https://en.wikipedia.org/wiki/Darts#/media/File:Darts_in_a_dartboard.jpg +[concentric]: https://mathworld.wolfram.com/ConcentricCircles.html +[cartesian-coordinates]: https://www.mathsisfun.com/data/cartesian-coordinates.html +[real-numbers]: https://www.mathsisfun.com/numbers/real-numbers.html +[habere-et-dispertire]: https://exercism.org/profiles/habere-et-dispertire +[inkscape]: https://en.wikipedia.org/wiki/Inkscape diff --git a/exercises/practice/darts/.meta/Example.cfc b/exercises/practice/darts/.meta/Example.cfc new file mode 100644 index 0000000..07627d6 --- /dev/null +++ b/exercises/practice/darts/.meta/Example.cfc @@ -0,0 +1,27 @@ +/** +* Your implementation of the Darts exercise +*/ +component { + + /** + * @returns + */ + function score( x, y) { + abs_x = Abs(x) + abs_y = Abs(y) + distance = Sqr(abs_x * abs_x + abs_y * abs_y) + if (distance <= 1) { + return 10 + } + else if (distance <= 5) { + return 5 + } + else if (distance <= 10) { + return 1 + } + else { + return 0 + } + } + +} \ No newline at end of file diff --git a/exercises/practice/darts/.meta/ExampleTest.cfc b/exercises/practice/darts/.meta/ExampleTest.cfc new file mode 100644 index 0000000..0c1033a --- /dev/null +++ b/exercises/practice/darts/.meta/ExampleTest.cfc @@ -0,0 +1,7 @@ +component extends="DartsTest" { + + function beforeAll(){ + SUT = createObject( 'Solution' ); + } + +} \ No newline at end of file diff --git a/exercises/practice/darts/.meta/config.json b/exercises/practice/darts/.meta/config.json new file mode 100644 index 0000000..7b20721 --- /dev/null +++ b/exercises/practice/darts/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "Darts.cfc" + ], + "test": [ + "DartsTest.cfc" + ], + "example": [ + ".meta/Example.cfc", + ".meta/ExampleTest.cfc" + ] + }, + "blurb": "Write a function that returns the earned points in a single toss of a Darts game.", + "source": "Inspired by an exercise created by a professor Della Paolera in Argentina" +} diff --git a/exercises/practice/darts/.meta/tests.toml b/exercises/practice/darts/.meta/tests.toml new file mode 100644 index 0000000..fbe2976 --- /dev/null +++ b/exercises/practice/darts/.meta/tests.toml @@ -0,0 +1,49 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[9033f731-0a3a-4d9c-b1c0-34a1c8362afb] +description = "Missed target" + +[4c9f6ff4-c489-45fd-be8a-1fcb08b4d0ba] +description = "On the outer circle" + +[14378687-ee58-4c9b-a323-b089d5274be8] +description = "On the middle circle" + +[849e2e63-85bd-4fed-bc3b-781ae962e2c9] +description = "On the inner circle" + +[1c5ffd9f-ea66-462f-9f06-a1303de5a226] +description = "Exactly on center" + +[b65abce3-a679-4550-8115-4b74bda06088] +description = "Near the center" + +[66c29c1d-44f5-40cf-9927-e09a1305b399] +description = "Just within the inner circle" + +[d1012f63-c97c-4394-b944-7beb3d0b141a] +description = "Just outside the inner circle" + +[ab2b5666-b0b4-49c3-9b27-205e790ed945] +description = "Just within the middle circle" + +[70f1424e-d690-4860-8caf-9740a52c0161] +description = "Just outside the middle circle" + +[a7dbf8db-419c-4712-8a7f-67602b69b293] +description = "Just within the outer circle" + +[e0f39315-9f9a-4546-96e4-a9475b885aa7] +description = "Just outside the outer circle" + +[045d7d18-d863-4229-818e-b50828c75d19] +description = "Asymmetric position between the inner and middle circles" diff --git a/exercises/practice/darts/Darts.cfc b/exercises/practice/darts/Darts.cfc new file mode 100644 index 0000000..2a717cd --- /dev/null +++ b/exercises/practice/darts/Darts.cfc @@ -0,0 +1,13 @@ +/** +* Your implementation of the Darts exercise +*/ +component { + + /** + * @returns + */ + function score( x, y ) { + // Implement me here + } + +} \ No newline at end of file diff --git a/exercises/practice/darts/DartsTest.cfc b/exercises/practice/darts/DartsTest.cfc new file mode 100644 index 0000000..199b642 --- /dev/null +++ b/exercises/practice/darts/DartsTest.cfc @@ -0,0 +1,67 @@ +component extends="testbox.system.BaseSpec" { + + function beforeAll(){ + SUT = createObject( 'Darts' ); + } + + function run(){ + + describe( "My Darts class", function(){ + + it( 'Missed target', function(){ + expect( SUT.score( x=-9, y=9 ) ).toBe( 0 ); + }); + + it( 'On the outer circle', function(){ + expect( SUT.score( x=0, y=10 ) ).toBe( 1 ); + }); + + it( 'On the middle circle', function(){ + expect( SUT.score( x=-5, y=0 ) ).toBe( 5 ); + }); + + it( 'On the inner circle', function(){ + expect( SUT.score( x=0, y=-1 ) ).toBe( 10 ); + }); + + it( 'Exactly on center', function(){ + expect( SUT.score( x=0, y=0 ) ).toBe( 10 ); + }); + + it( 'Near the center', function(){ + expect( SUT.score( x=-0.1, y=-0.1 ) ).toBe( 10 ); + }); + + it( 'Just within the inner circle', function(){ + expect( SUT.score( x=0.7, y=0.7 ) ).toBe( 10 ); + }); + + it( 'Just outside the inner circle', function(){ + expect( SUT.score( x=0.8, y=-0.8 ) ).toBe( 5 ); + }); + + it( 'Just within the middle circle', function(){ + expect( SUT.score( x=-3.5, y=3.5 ) ).toBe( 5 ); + }); + + it( 'Just outside the middle circle', function(){ + expect( SUT.score( x=-3.6, y=-3.6 ) ).toBe( 1 ); + }); + + it( 'Just within the outer circle', function(){ + expect( SUT.score( x=-7.0, y=7.0 ) ).toBe( 1 ); + }); + + it( 'Just outside the outer circle', function(){ + expect( SUT.score( x=7.1, y=-7.1 ) ).toBe( 0 ); + }); + + it( 'Asymmetric position between the inner and middle circles', function(){ + expect( SUT.score( x=0.5, y=-4 ) ).toBe( 5 ); + }); + + }); + + } + +} \ No newline at end of file diff --git a/exercises/practice/darts/TestRunner.cfc b/exercises/practice/darts/TestRunner.cfc new file mode 100644 index 0000000..762b153 --- /dev/null +++ b/exercises/practice/darts/TestRunner.cfc @@ -0,0 +1,103 @@ +/** +* I am a CommandBox task runner which you can use to test your implementation of this exercise against the +* provided test suite. To use me, open the CommandBox CLI and run this: +* +* CommandBox> task run TestRunner +* +* To start up a test watcher that will automatically rerun the test suite every time you save a file change, run this: +* +* CommandBox> task run TestRunner --watcher +* +*/ +component { + + /** + * @solution Runs the tests against the solution + * @watcher Start up a file watch that re-runs the tests on file changes. Use Ctrl-C to stop + */ + function run( boolean solution=false, boolean watcher=false ) { + + ensureTestBox(); + + if( watcher ) { + + // Tabula rasa + command( 'cls' ).run(); + + // Start watcher + watch() + .paths( '*.cfc' ) + .inDirectory( getCWD() ) + .withDelay( 500 ) + .onChange( function() { + + // Clear the screen + command( 'cls' ) + .run(); + + // This is neccessary so changes to tests get picked up right away. + pagePoolClear(); + + runTests( solution ); + + } ) + .start(); + + } else { + runTests( solution ); + } + + } + + /** + * Make sure the TestBox framework is installed + */ + private function ensureTestBox() { + var excerciseRoot = getCWD(); + var testBoxRoot = excerciseRoot & '/testbox'; + + if( !directoryExists( testBoxRoot ) ) { + + print.boldYellowLine( 'Installing some missing dependencies for you!' ).toConsole(); + command( 'install' ) + .inWorkingDirectory( excerciseRoot ) + .run(); + } + + // Bootstrap TestBox framework + filesystemUtil.createMapping( '/testbox', testBoxRoot ); + } + + /** + * Invoke TestBox to run the test suite + */ + private function runTests( boolean solution=false ) { + + // Create TestBox and run the tests + testData = new testbox.system.TestBox() + .runRaw( directory = { + // Find all CFCs... + mapping = filesystemUtil.makePathRelative( getCWD() ), + // ... in this directory ... + recurse = false, + // ... whose name ends in "test" + filter = function( path ) { + return path.reFind( ( solution ? 'Solution' : '' ) & 'Test.cfc$' ); + } + } ) + .getMemento(); + + // Print out the results with ANSI formatting for the CLI + getInstance( 'CLIRenderer@testbox-commands' ) + .render( print, testData, true ); + + print.toConsole(); + + // Set proper exit code + if( testData.totalFail || testData.totalError ) { + setExitCode( 1 ); + } + } + +} + diff --git a/exercises/practice/darts/box.json b/exercises/practice/darts/box.json new file mode 100644 index 0000000..3b95f7e --- /dev/null +++ b/exercises/practice/darts/box.json @@ -0,0 +1,8 @@ +{ + "dependencies":{ + "testbox":"^2.5.0+107" + }, + "installPaths":{ + "testbox":"testbox/" + } +} \ No newline at end of file diff --git a/exercises/practice/darts/index.cfm b/exercises/practice/darts/index.cfm new file mode 100644 index 0000000..1e35079 --- /dev/null +++ b/exercises/practice/darts/index.cfm @@ -0,0 +1,37 @@ + + + + + // get a list of all CFCs in this folder whose name looks like "XXXTest.cfc" + // And turn it into compnent path relative to the web root + url.bundles = directoryList( + path=expandPath( '/' ), + filter='*Test.cfc' ) + .map( function( path ) { + return path + .replaceNoCase( expandPath( '/' ), '' ) + .left( -4 ) + } ) + .toList(); + + + + + + + + Oops, you don't have TestBox installed yet! Please run box install from the root of your excercise folder and refresh this page. + From dedb9f4111bbb3451fe108c4e05c3ec873035a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:29:12 -0800 Subject: [PATCH 2/2] Fix inadvertent config formatting --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 18211d3..8c43776 100644 --- a/config.json +++ b/config.json @@ -355,7 +355,7 @@ "content": "Easily access databases, natively convert HTML to PDF, parse XML, spin up APIs, or write to S3.", "icon": "cross-platform" } - ], + ], "tags": [ "paradigm/declarative", "typing/dynamic", @@ -366,4 +366,4 @@ "used_for/frontends", "used_for/web_development" ] -} \ No newline at end of file +}