Coder Social home page Coder Social logo

adventure-map's Introduction

adventure-map

Tools with sensible defaults for guiding the creation of new adventure workshops.

  • Coloured syntax highlighting in exercise descriptions.
  • Prints syntax highlighted solution on completion of an exercise.
  • Add optional exercise boilerplate.
  • Generates a user solution directory for each exercise.
  • User solution directory includes exercise boilerplate & problem description.

Code generators for easily starting new workshops & exercises:

  • Generate a new workshop with adventure-map init. Creates minimal bootstrap (~20 LOC).
  • Generate a new exercise with adventure-map new exercise-name: Bootstraps a few default files for an exercise (Readme.md, bootstrap.js, solution.js & verify.js)

I normally hate code generators so I've tried to make the code generation only spit out the most unopinionated code that you probably would have written anyway. All generated code is extremely simple and makes minimal assumptions. You can safely and easily modify the generated code to work however you wish.

TODO: custom code generation templates.

CLI Usage

> adventure-map --help
  Usage:
    adventure-map init         Bootstrap current directory.
    adventure-map new [name]   Bootstrap new exercise with [name].

Generating Adventures

You can use adventure-map to generate the minimal boilerplate for an entire adventure. It includes a bootstrap file to load all the exercises and an example exercise to use as a guide.

> mkdir test-adventure
> cd test-adventure
> npm init -f
> npm install --save adventure-map
> adventure-map init
exercises/example/Readme.md
exercises/example/boilerplate.js
exercises/example/index.js
exercises/example/solution.js
index.js

By default, exercises are loaded as "name": "relative/path/to/exercise" pairs from your package.json. You need to add exercises to the package.json manually.

{
  "name": "test-adventure",
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "adventure-map": "1.0.0"
  },
  "exercises": {
    "Getting Started": "exercises/example"
  }
}

If you don't like this convention of loading from the package.json, just change where the exercises load from, it's one line of code in the bootstrap code (see below).

After you've configured at least one exercise, can start your adventure:

> node index.js

image

Adventure Bootstrap Code

The adventure bootstrap simply finds the exercises defined in your package.json and loads them into adventure.

#!/usr/bin/env node

var path = require('path')
var adventureMap = require('adventure-map')
var pkg = require('./package.json')

// resolve all package.json exercises relative
// to this directory.
Object.keys(pkg.exercises).forEach(function(name) {
  pkg.exercises[name] = path.resolve(__dirname, pkg.exercises[name])
})

var adventure = adventureMap(pkg)

// auto-execute if run from commandline
if (!module.parent) adventure.execute(process.argv.slice(2))

// export for manual execution
module.exports = adventure

Important

The boilerplate is just provided as a starting point, don't feel bad about changing any of the generated code.

Generating Exercises

You can use adventure-map to generate the required boilerplate for an exercise:

> adventure-map new getting-started
exercises/getting-started/Readme.md
exercises/getting-started/boilerplate.js
exercises/getting-started/index.js
exercises/getting-started/solution.js

The exercise's script will load up the Readme, boilerplate and solution text for you, and provide a verify stub.

Exercise Bootstrap Code

"use strict"

var fs = require('fs')
var path = require('path')

exports.problem = fs.readFileSync(__dirname + '/Readme.md', 'utf8')
exports.solution = fs.readFileSync(__dirname + '/solution.js', 'utf8')
exports.boilerplate = fs.readFileSync(__dirname + '/boilerplate.js', 'utf8')

var solution = require('./solution')

exports.verify = function(args, cb) {
  var submission = require(path.resolve(process.cwd(), args[0]))
  // insert validation logic
  cb(false) // true if submission good
}

exports.run = function() {
  // TODO
}

API Usage

You don't need to use the generated boilerplate in order to use adventure-map! Just pass it the adventure name and a mapping of exercise names and corresponding exercise paths.

You'll be passed back a substack/adventure instance.

var r = require('path').resolve
var adventureMap = require('adventure-map')

var adventure = adventureMap({
  name: 'test-adventure',
  exercises: {
    'Getting Started': r(__dirname, 'exercises/getting-started'),
    'Learning Things': r(__dirname, 'exercises/learning-things')
  }
})

adventure.execute(process.argv.slice(2))

Exercise Format

adventure-map exercises follow the same format as adventure exercises, with an additional boilerplate property:

module.exports = {
  problem: 'problem text',
  solution: 'solution code',
  boilerplate: 'boilerplate code' // optional
  verify: function(args, cb) {
    // insert validation logic
    cb(false) // true if submission good
  },
  run: function() {
    // optional 'run' logic
  }
}

Credit

License

MIT

adventure-map's People

Contributors

davidmason avatar timoxley avatar weilu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

adventure-map's Issues

Generated adventures print a stacktrace at the end of problem printout

I am getting an exception from the initial boilerplate code that adventure-map generates. It looks like it is triggered from a few levels down the dependency tree.

I am using Fedora 20, so I suspect it may be a platform-specific issue. Can someone have a go at reproducing this on a different OS?

To reproduce:

  1. run npm init -f
  2. run npm install --save adventure-map
  3. run adventure-map init
  4. add name+path pair to package.json: "exercises": { "Getting Started": "exercises/example" }
  5. run ./index.js
  6. select "Getting Started" and press Enter

Generates the following output


    ES5-WORKSHOP                                                       
    ------------                                                       
    Getting Started                                                    
    -----------------                                                  
    HELP                                                               
    EXIT                                                               



Lengthy introduction of concepts up here.

-------------------------------------------------------------------------------

# Task

Concise description of task.

## Example

    // example of usage

## Arguments

  * arg1: Description including data type

## Conditions

  * Do and
  * Do not

## Hints

  * Remember to give hints

## Resources

  * http://google.com

/home/damason/src/davidmason/es5-workshop


tty.js:65
  this._handle.setRawMode(flag);
               ^
TypeError: Cannot call method 'setRawMode' of null
    at ReadStream.setRawMode (tty.js:65:16)
    at Interface._setRawMode (readline.js:165:23)
    at new Interface (readline.js:126:10)
    at Object.exports.createInterface (readline.js:39:10)
    at Object.Interface.createInterface (/home/damason/src/davidmason/es5-workshop/node_modules/adventure-map/node_modules/inquirer/node_modules/readline2/index.js:38:21)
    at PromptUI.UI (/home/damason/src/davidmason/es5-workshop/node_modules/adventure-map/node_modules/inquirer/lib/ui/baseUI.js:23:40)
    at new PromptUI (/home/damason/src/davidmason/es5-workshop/node_modules/adventure-map/node_modules/inquirer/lib/ui/prompt.js:26:8)
    at Object.inquirer.prompt (/home/damason/src/davidmason/es5-workshop/node_modules/adventure-map/node_modules/inquirer/lib/inquirer.js:39:16)
    at setup (/home/damason/src/davidmason/es5-workshop/node_modules/adventure-map/index.js:66:14)
    at null._onTimeout (/home/damason/src/davidmason/es5-workshop/node_modules/adventure-map/index.js:43:9)

stdout does not close after help, exit or instruction output

This meas the user has to press Enter to get back to the command line.

This is an inadvertent effect of #5. I have not yet found a good way to override the autoclose behaviour for separate commands so that autoclose can be prevented just when instructions are printed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.