{"id":16721592,"url":"https://github.com/zoltan-nz/toy-robot-typescript","last_synced_at":"2026-02-26T18:36:38.194Z","repository":{"id":144596632,"uuid":"71993881","full_name":"zoltan-nz/toy-robot-typescript","owner":"zoltan-nz","description":"TypeScript project for beginners...","archived":false,"fork":false,"pushed_at":"2017-03-13T05:43:39.000Z","size":117,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-13T22:32:13.678Z","etag":null,"topics":["mocha","toy-robot","tutorial","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zoltan-nz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-10-26T10:48:54.000Z","updated_at":"2018-04-22T07:22:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"e87cca1f-9d0c-4755-8b3f-dac984b2160e","html_url":"https://github.com/zoltan-nz/toy-robot-typescript","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zoltan-nz%2Ftoy-robot-typescript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zoltan-nz%2Ftoy-robot-typescript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zoltan-nz%2Ftoy-robot-typescript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zoltan-nz%2Ftoy-robot-typescript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zoltan-nz","download_url":"https://codeload.github.com/zoltan-nz/toy-robot-typescript/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225700964,"owners_count":17510448,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mocha","toy-robot","tutorial","typescript"],"created_at":"2024-10-12T22:31:28.175Z","updated_at":"2026-02-26T18:36:33.159Z","avatar_url":"https://github.com/zoltan-nz.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Getting Started with TypeScript\n\nPracticing Typescript with the Toy Robot exercise.\n\n## How to run this project?\n\nPlease, use Node.js v6 and install `yarn` as package manager.\n\n```shell\n$ yarn\n$ yarn start\n```\n\n**For development**, run the following commands in separate shells.\n\n```shell\n$ yarn watch\n```\n\n```shell\n$ yarn watch:launch\n```\n\n```shell\n$ yarn watch:test\n```\n\n**Coverage report**\n\n```shell\n$ yarn test:coverage\n```\n\n## Ideal development environment\n\nGreat scaffolder: https://github.com/ospatil/generator-node-typescript\n\n### Install packages\n\nGlobals\n```\n$ yarn global add tslint typescript\n```\n\nDev packages\n\n```\n$ yarn add --dev tslint mocha chai typescript typings ts-node rimraf sinon-chai\n```\n\nTyping packages\n```\n$ yarn add --dev @types/chai @types/mocha @types/node @types/sinon-chai\n```\n\n### Setup `tsconfig.json`\n\n```json\n{\n  \"compilerOptions\": {\n    \"declaration\": true,\n    \"outDir\": \"./lib\",\n    \"sourceMap\": true,\n    \"noImplicitAny\": true,\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"node\"\n  },\n  \"include\": [\n    \"src/**/*\"\n  ],\n  \"compileOnSave\": true\n}\n```\n\n* The `exclude` property only affects the files included via the `include` property.\n\n### Setup `tslint.json`\n\n```json\n{\n  \"extends\": \"tslint:latest\",\n  \"rules\": {\n    \"curly\": false,\n    \"quotemark\": [true, \"single\", \"avoid-escape\"]\n  }\n}\n```\n\n### Notes for type declaration\n\n* Doesn't need `typings`, because TypeScript 2 manages it automatically, however we have to install declaration file as node modules.\n* Search on: https://microsoft.github.io/TypeSearch/, for example search for `sinon-chai`.\n\n### Setup `.vscode` shorthands\n\n`.vscode/settings.json` - VS Code will use the installed TypeScript version\n```json\n{\n  \"typescript.tsdk\": \"./node_modules/typescript/lib\"\n}\n```\n\n`.vscode/tasks.json`\n```json\n{\n  \"version\": \"0.1.0\",\n  \"command\": \"npm\",\n  \"isShellCommand\": true,\n  \"args\": [\"run\"],\n  \"showOutput\": \"always\",\n  \"tasks\": [{\n      \"taskName\": \"build\",\n      \"isBuildCommand\": true\n    },\n    {\n      \"taskName\": \"clean\"\n    },\n    {\n      \"taskName\": \"lint\"\n    },\n    {\n      \"taskName\": \"test\",\n      \"isTestCommand\": true\n    }\n  ]\n}\n```\n\n### Other setup\n\n* `.editorconfig` \n* `.jsbeautifyrc`\n\n### Add script to package.json\n\nReading: `npm help scripts`\n\n```\n$ yarn run clean\n$ yarn lint\n$ yarn build\n$ yarn test\n$ yarn watch\n$ yarn watch:test\n$ yarn watch:launch\n```\n\nIn `package.json`:\n\n```json\n\"scripts\": {\n    \"clean\": \"rimraf lib .nyc-output coverage\",\n    \"lint\": \"tslint --force --fix \\\"src/**/*.ts\\\" \\\"test/**/*.ts\\\"\",\n    \"prebuild\": \"yarn lint\",\n    \"build\": \"yarn run clean \u0026\u0026 echo Using TypeScript \u0026\u0026 tsc --version \u0026\u0026 tsc --pretty\",\n    \"pretest\": \"yarn build\",\n    \"test\": \"mocha\",\n    \"testOnly\": \"mocha\",\n    \"test:coverage\": \"nyc yarn test \u0026\u0026 open coverage/index.html\",\n    \"prepublish\": \"yarn test\",\n    \"watch\": \"yarn build -- --watch\",\n    \"watch:test\": \"yarn test -- --watch\",\n    \"watch:launch\": \"nodemon lib/main\",\n    \"prestart\": \"yarn build\",\n    \"start\": \"node ./lib/main\"\n  },\n```\n\nWe can install as a command line line tool: `npm install -g .`\n\n### Relaunch application after code change\n\n```sh\n$ yarn global install nodemon\n\n$ nodemon lib/main\n```\n\n### Test with mocha\n\n* Mocha default test folder is `./test`\n* Settings can be saved in `mocha.opts`, so a simple `mocha` command can run all the test\n* Debug mocha:\n\n```json\n// launch.json\n    {\n      \"name\": \"Run mocha test\",\n      \"type\": \"node2\",\n      \"request\": \"launch\",\n      \"program\": \"${workspaceRoot}/node_modules/.bin/_mocha\",\n      \"cwd\": \"${workspaceRoot}\"\n    }\n```\n\n* `Chai` is a simple expectation library [web](http://chaijs.com/guide/styles/#expect)\n\n### Code coverage\n\nhttps://github.com/istanbuljs/nyc\n\n```sh\n$ yarn add --dev nyc\n```\n\n.nycrc\n```json\n{\n  \"include\": [\n    \"src/**/*.ts\"\n  ],\n  \"exclude\": [\n    \"typings\",\n    \"@types\",\n    \"node_modules\",\n    \"coverage\",\n    \".nyc_output\",\n    \"lib\",\n    \"test/**/*.ts\"\n  ],\n  \"extension\": [\n    \".ts\"\n  ],\n  \"require\": [\n    \"ts-node/register\"\n  ],\n  \"reporter\": [\n    \"json\",\n    \"html\"\n  ],\n  \"all\": true\n}\n```\n\n# Toy Robot Simulator\n\n[Original example](https://github.com/DiscoverRedwolf/toyrobot)\n\n- A toy robot moving on a square tabletop.\n- Table top dimensions: 5 units x 5 units.\n- Robot cannot move out from the tabletop.\n\nCommands:\n\n```\nPLACE X,Y,F\nPLACE will put the toy robot on the table in position X,Y and facing NORTH, SOUTH, EAST or WEST.\nThe origin (0,0) can be considered to be the SOUTH WEST most corner.\nThe first valid command to the robot is a PLACE command, after that, any sequence of commands may be issued, \nin any order, including another PLACE command. The application should discard all commands in the sequence until \na valid PLACE command has been executed.\n```\n```\nMOVE\nMOVE will move the toy robot one unit forward in the direction it is currently facing.\n```\n```\nLEFT, RIGHT\nLEFT and RIGHT will rotate the robot 90 degrees in the specified direction without changing the position of the robot.\n```\n```\nREPORT\nREPORT will announce the X,Y and F of the robot. This can be in any form, but standard output is sufficient.\n```\nRestrictions:\n* A robot that is not on the table can choose the ignore the MOVE, LEFT, RIGHT and REPORT commands.\n* Input can be from a file, or from standard input.\n* The toy robot must not fall off the table during movement. This also includes the initial placement of the toy robot. Any move that would cause the robot to fall must be ignored.\n\nExample Input and Output:\n* `PLACE 0,0,NORTH MOVE REPORT` Output: `0,1,NORTH`\n* `PLACE 0,0,NORTH LEFT REPORT` Output: `0,0,WEST`\n* `PLACE 1,2,EAST MOVE MOVE LEFT MOVE REPORT` Output: `3,3,NORTH`\n\n## Notes\n\n* Add lodash to the project\n* Useful lodash methods: flattenDeep, sum, fill\n* Add nice table presentation in console: [cli-table]()https://github.com/jamestalmage/cli-table2)\n\nDealing with non-typed packages:\n\n* https://github.com/Microsoft/TypeScript/issues/9184\n* Create a `@types` folder for type definitions\n* Extend `tsconfig.json` with `\"typeRoots\": [\"@types\"]` to `compilerOptions`\n\n```\ndeclare class SomeClass {\n  constructor(options?: Object);\n}\n\ndeclare module 'module_name' {\n  export = SomeClass\n}\n```\n\n### Robot\n\nRequirements:\n* Robot exists (creating an instance)\n* Robot can turn LEFT, RIGHT (actions)\n* Robot instance stores the direction where its facing (state holder)\n\nImplementation notes:\n* Using interface for options\n* Using enums for constans\n* Has to `export` them, so they can be used during initialization\n* Flexible interface: all params with `?`\n* Constructor with an empty object, so initialization can be done without any params\n* Merging passed parameters with the default values in constructor\n\n### Debug \n\nMocha with node --inspector\n```sh\n$ node --inspect --debug-brk node_modules/.bin/_mocha --watch\n```\n\nCompiled lib/main.js\n```sh\n$ node --inspect --debug-brk lib/main\n```\n\n### Moving robot\n\n* Where should store the actual position coordinates of a robot? Robot responsibility is direction and turning left/right only.\n* In our simplified example, Table class can store the state of a robot, however the best option if we have a Traffic manager, a controller, which can connect together our table with our robot... maybe later we would like to add more robot to our program.\n* Table instance can store: which coordinate is not empty and who is on that position. (out of scope)\n \n### TTY and Readline notes\n\n```js\nimport * as readline from 'readline';\n\n// Move the cursor top-left corner\nreadline.cursorTo(process.stdout, 0, 0)\n\n// We can watch each keypress\nreadline.emitKeypressEvents(process.stdin);\n\n// Clear the whole console\nreadline.clearScreenDown(process.stdout);\n\n// Watching resize\nprocess.stout.on('resize', () =\u003e {\n      console.log(`${process.stdout.columns}x${process.stdout.rows}`);\n})\n\n// Watching keystrokes\n/* key: {\n *   sequence: '',\n *   name: '',\n *   ctrl: false,\n *   meta: false,\n *   shift: false\n * }\n */\nprocess.stdin.on('keypress', (str, key) =\u003e {\n  if (key.ctrl \u0026\u0026 key.name === 'c') {\n    process.exit();\n  }\n  \n})\n```\nTTY console exists only when the app run natively with node command. Using `nodemon` or `forever` run the app as a separate process, the console is not TTY anymore, so watching `keypress` is not a solution.\n\nChanging the requirement: using standard readline for sending commands, so there will be always an Enter at the end.\n(Secondary option to control with keystrokes... Interesting package: https://github.com/SBoudrias/Inquirer.js)\n\n### Creating a ScreenWriter class for managing drawing\n\n- [x] should be a singleton\n- [x] should write out given content\n- [x] should clear the page\n\nUseful readings: https://www.joyent.com/node-js/production\n\n### Notes about Streams\n\nImportant: https://nodejs.org/api/stream.html#stream_types_of_streams\n\nSetup a stream from a `ChildProcess`:\n```js\nconst mainApp: ChildProcess = childProcess.execFile('node', ['lib/main.js']);\n```\n\nWatch and read console content:\n```js\nmainApp.stdout.on('data', (data) =\u003e {\n  content = content + data;\n});\n```\n\nWatch end event:\n```js\nmainApp.stdout.on('end', () =\u003e {\n  const aRow: string = '│  │  │  │  │  │';\n  expect(content).to.contains(aRow);\n  done();\n});\n```\n\n* Watching `data` and `end` is an old way to manage Streams.\n* New way: `pipe` it or watch `readable` event and deal with the Buffer.\n\nSend a `ctrl-c` keystroke to the app:\n```js\nmainApp.stdin.write('\\x03');\n```\n\n**Mocking stdout.write stream**\n\n* https://www.npmjs.com/package/stdio-mock\n* https://github.com/TylorS/stdio-mock\n\nWe can create a dummy Writable stream as a mock, overwrite the original process.stdout.write with this mock and we can watch the data on this mocked stream. We can test the diverted content.\n\nFinally, after refactoring ScreenWriter a little bit, actually adding an optional parameter to the constructor, we can inject the writable stream, so we can directly test on that injected stream.\n \n### Controller\n\nNeed a place where we can merge together robots with table, etc...\n\nLet's use the `main` method first and we can refactor later.\n\nstdin https://github.com/sindresorhus/get-stdin/blob/master/index.js\n\n### Notes about Promise\n\nOption 1:\nUse native Promise if target is \"es6\"\n\nOption 2:\nAdd @types/es6-promise if target is \"es5\"\n\n### Command Line parser\n\n1. Loop until quit command\n2. Do what the command say\n\n#TODO\n\n- [x] Create a Table top class\n- [x] Create a Robot class\n- [x] Controller connect together Table with Robot\n- [x] Command line parser\n\nProbably a better option if the robot knows about its position\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzoltan-nz%2Ftoy-robot-typescript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzoltan-nz%2Ftoy-robot-typescript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzoltan-nz%2Ftoy-robot-typescript/lists"}