{"id":24655170,"url":"https://github.com/xtenzq/atm-java","last_synced_at":"2025-03-21T02:16:33.795Z","repository":{"id":115828486,"uuid":"439814644","full_name":"xtenzQ/atm-java","owner":"xtenzQ","description":"Cash Machine test task for a Back End Developer position","archived":false,"fork":false,"pushed_at":"2021-12-20T14:32:10.000Z","size":322,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-21T02:16:28.536Z","etag":null,"topics":["atm","cashmachine","command-pattern","interview-task","oop-java","test-task"],"latest_commit_sha":null,"homepage":"https://xtenzq.github.io/kmslh-test","language":"Java","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/xtenzQ.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":"2021-12-19T08:42:25.000Z","updated_at":"2025-01-01T13:21:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"6a14cecc-8ba0-481a-8b60-e65b406f7634","html_url":"https://github.com/xtenzQ/atm-java","commit_stats":null,"previous_names":["xtenzq/atm-java"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtenzQ%2Fatm-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtenzQ%2Fatm-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtenzQ%2Fatm-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtenzQ%2Fatm-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xtenzQ","download_url":"https://codeload.github.com/xtenzQ/atm-java/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244722744,"owners_count":20499154,"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":["atm","cashmachine","command-pattern","interview-task","oop-java","test-task"],"created_at":"2025-01-25T22:36:20.083Z","updated_at":"2025-03-21T02:16:33.789Z","avatar_url":"https://github.com/xtenzQ.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cash Machine Back End Developer Position Test Task\n\n[![build](https://github.com/xtenzQ/kmslh-test/actions/workflows/maven.yml/badge.svg)](https://github.com/xtenzQ/kmslh-test/actions/workflows/maven.yml)\n[![test](https://github.com/xtenzQ/kmslh-test/actions/workflows/test-coverage.yml/badge.svg?branch=main)](https://github.com/xtenzQ/kmslh-test/actions/workflows/test-coverage.yml)\n![Coverage](https://github.com/xtenzQ/kmslh-test/blob/main/.github/badges/jacoco.svg)\n\nA friendly reminder: If this repo somehow helped you please **star** 🌟 it! Thank you! 😄\n\n## Task\n\nIs to create simple Cash Machine emulator.\n\n_Requirements_ **(9/9 completed)**:\n- [x] create stand-alone console I/O Java program using any JDK;\n- [x] follow OOP paradigm;\n- [x] make program easily extendable;\n- [x] provide logging to the output file;\n- [x] divide program modules into packages;\n- [x] generate JavaDocs;\n- [x] write JUnit tests for public methods;\n- [x] make Ant `build.xml`;\n- [x] make functional test.\n\nInput commands:\n1. **Cash deposit** \n```Bash\nFormat: + \u003ccurrency\u003e \u003cdenomination\u003e \u003camount\u003e\nValidation: \n* \u003ccurrency\u003e 3 uppercase letters, any combination\n* \u003cvalue\u003e any value in set [\"1\",\"5\",\"10\",\"50\",\"100\",\"500\",\"1000\",\"5000\"]\n* \u003cnumber\u003e positive integer\nReply: OK on success, ERROR on validation fail\n```\n\n2. **Cash withdraw**\n```Bash\nFormat: - \u003ccurrency\u003e \u003camount\u003e\nReply: line formatted as \u003cdenomination\u003e \u003camount\u003e followed by OK on success, ERROR if amount is unavailable\n```\n\n3. **Cash print**\n```Bash\n Format: ?\n Reply: OK, ordered by currency -\u003e value\n```\n\n# Run, build and test\n\n### Build\n\n```Bash\nant build\n```\n\n### Test\n\n```Bash\nant test\n```\n\n### Run\n\n```Bash\nant run\n```\n\n# Solution\n\nBefore coding, we should make a plan:\n1. How to handle commands;\n2. Deposit/Withdraw strategy;\n3. I/O common interface.\n\n### Commands handling\n\nTo handle the command problem I decided to go for behavioral design **[Command pattern](https://en.wikipedia.org/wiki/Command_pattern)** which delegates command build to the command factory.\n\nI recommend to check **[Jairo Alfaro's reply](https://stackoverflow.com/a/46968141)** on StackOverflow since he gives a good example of the implementation in C#. \n\n### Deposit/Withdraw strategy\n\nI decided to arrange data in a structure `Map\u003cString, TreeMap\u003cInteger, Integer\u003e\u003e` since we basically have this kind of structure:\n\n![Structure](struct.png)\n\nSince we have to pop up bigger banknotes first, we store `Map\u003cInteger, Integer\u003e` in a reverse order. In Java, `TreeMap\u003cInteger, Integer\u003e` stores keys in a natural order, so in our case we should apply `Collections.reverseOrder()` on initialization.\n\nThe rest of the algorithm is a piece of cake. For the deposit we simply add cash to the denomination, for the withdrawal we subtract the amount of remove the denomination if the amount is exact. Also, handle the situation when amount is unavailable (denomination absence, etc.).\n\n### I/O common interface\n\nI created an I/O interface (`InputReader` \u0026 `OutputWriter`) and implemented corresponding reader and writer to work with streams. These classes can work both with `System.in`/`System.out` and `FileInputStream`/`FileOutputStream` so we can easily switch between file and console I/O.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxtenzq%2Fatm-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxtenzq%2Fatm-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxtenzq%2Fatm-java/lists"}