[
  {
    "path": ".eslintrc.js",
    "content": "\nmodule.exports = {\n    extends: ['eslint:recommended', 'prettier'], // extending recommended config and config derived from eslint-config-prettier\n    plugins: ['prettier'], // activating esling-plugin-prettier (--fix stuff)\n    env: {\n      \"browser\": true,\n      \"es6\": true,\n      \"node\": true\n    },\n    parserOptions: {\n      sourceType: \"module\",\n      ecmaVersion: \"2018\",\n      allowImportExportEverywhere: false,\n      ecmaFeatures: {\n        globalReturn: false,\n      }\n    },\n    rules: {\n      \"no-console\": 0,\n      'prettier/prettier': [ // customizing prettier rules (unfortunately not many of them are customizable)\n        'error',\n        {\n          singleQuote: true,\n          trailingComma: 'all',\n        },\n      ],\n      eqeqeq: ['error', 'always'], // adding some custom ESLint rules\n    },\n  };\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "ko_fi: jamesgeorge007\npatreon: jamesgeorge007\ncustom: https://www.paypal.me/jamesgeorge007\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\n<!--Steps to reproduce the behavior:-->\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Environment Information**\n<!-- Specify your local environment information such as the OS -->\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/custom.md",
    "content": "---\nname: Custom issue template\nabout: Describe this issue template's purpose here.\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n## Do you want to request a feature or report a bug?\n\n## What is the current behavior?\nIf the current behavior is a bug, please provide the steps to reproduce.\n\n## What is the expected behavior?\nIf this is a feature request, what is motivation or use case for changing the behavior?\n\n## Local Environment Information\nPlease paste the results of `teachcode info` here.\n\n## Screenshots\nIf applicable, add screenshots to help explain your problem.\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: 'feat:'\nlabels: feature-request\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->\n\n**What kind of change does this PR introduce?**\n<!-- E.g. a bugfix, feature, refactoring, build related change, etc… -->\n\n**Did you add tests for your changes?**\n\n**If relevant, did you update the documentation?**\n\n**Summary**\n\n<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->\n<!-- Try to link to an open issue for more information. -->\n\n**Does this PR introduce a breaking change?**\n<!-- If this PR introduces a breaking change, please describe the impact and a migration path for existing applications. -->\n\n**Other information**"
  },
  {
    "path": ".github/config.yml",
    "content": "# ProBot Request Info (https://probot.github.io/apps/request-info/)\n\nrequestInfoReplyComment: >\n  We would appreciate it if you could provide us with more info about this issue/pr!\n\nrequestInfoLabelToAdd: needs-more-info\n\n# ProBot Welcome (https://probot.github.io/apps/welcome/)\n\nnewIssueWelcomeComment: >\n  Thanks for opening your first issue here! Be sure to follow the issue template!\n\nnewPRWelcomeComment: >\n  Thanks for opening this pull request! Please check out our contributing guidelines.\n\nfirstPRMergeComment: >\n  ![congrats](https://media1.giphy.com/media/xT0xezQGU5xCDJuCPe/giphy.gif)\n\n  Congrats on your very first contribution :clap: Looking forward to having more from your side\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\non:\n  push:\n  pull_request:\n    branches:\n      - master\n      - next\n  workflow_dispatch:\njobs:\n  job:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-latest, macos-latest, windows-latest]\n        node: [16, 18, 20]\n    steps:\n      - uses: actions/checkout@v2\n      - name: Setup node\n        uses: actions/setup-node@v2\n        with:\n          node-version: ${{ matrix.node }}\n          cache: 'npm'\n      - name: Install packages\n        run: npm ci\n      - name: Run e2e tests\n        run: npm run test"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# VS-Code config\n.vscode\n\n# vuepress dist\ndocs/.vuepress/dist\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# TypeScript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# parcel-bundler cache (https://parceljs.org/)\n.cache\n\n# next.js build output\n.next\n\n# nuxt.js build output\n.nuxt\n\n# vuepress build output\n.vuepress/dist\n\n# Serverless directories\n.serverless\n\n# FuseBox cache\n.fusebox/\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at founders@madlabs.xyz. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <a href=\"https://teachcode.madlabs.xyz/\"><img src=\"https://i.imgur.com/BuMZB6C.png\" width=\"240\" height=\"240\"></a>\n  <h1 align=\"center\">teachcode</h1>\n  <p align=\"center\"> A tool to develop and improve a student’s programming skills by introducing the earliest lessons of coding. </p>\n</p>\n\n<p align=\"center\">\n\t<a href=\"https://travis-ci.com/madlabsinc/teachcode\"><img src=\"https://travis-ci.com/madlabsinc/teachcode.svg?branch=master\" alt=\"Build Status\" /></a>\n\t<a href=\"https://www.npmjs.com/package/teach-code\"><img src=\"https://badgen.net/npm/v/teach-code\" alt=\"npm version\" /></a>\n\t<a href=\"https://www.npmjs.com/package/teach-code\"><img src=\"https://badgen.net/npm/dm/teach-code\" alt=\"Downloads\" /></a>\n\t<a href=\"https://github.com/madlabsinc/teachcode/pull/new\"><img src=\"https://img.shields.io/badge/PRs%20-welcome-brightgreen.svg\" alt=\"PRs Welcome\" /></a>\n\t<a href=\"https://github.com/prettier/prettier\"><img src=\"https://img.shields.io/badge/code_style-prettier-ff69b4.svg\" alt=\"code style: prettier\" /></a>\n\t<a href=\"https://github.com/ulivz/awesome-vuepress\"><img src=\"https://awesome.re/mentioned-badge.svg\" alt=\"Mentioned in Awesome-VuePress\" /></a>\n\t<a title=\"Chat on Telegram\" href=\"https://t.me/teach_code\"><img src=\"https://img.shields.io/badge/chat-Telegram-blueviolet?logo=Telegram\"/></a>\n\t<a href=\"https://twitter.com/intent/follow?screen_name=teachcode_cli\"><img src=\"https://img.shields.io/twitter/follow/teachcode_cli.svg?style=social&label=Follow%20@teachcode_cli\" alt=\"Follow on Twitter\"></a>\n</p>\n\n<p align=\"center\">\n\t<a href='https://www.buymeacoffee.com/jamesgeorge007' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://bmc-cdn.nyc3.digitaloceanspaces.com/BMC-button-images/custom_images/orange_img.png' border='0' alt='Buy Me a Coffee' /></a>\n</p>\n\n---\n\n**Chat: _[Telegram](https://t.me/teach_code)_**\n\n**Donate: _[PayPal](https://www.paypal.me/jamesgeorge007), [Patreon](https://www.patreon.com/jamesgeorge007)_**\n\n## Installation\n\n`npm install -g teach-code`\n\n## How to use\n\nUsers are required to solve 30 tasks that take them through the basic constructs of the programming language of their choice. The tasks are designed in such a way that the complexity increases as users progress through the tasks. One can't move forward until the current task is completed. Previously submitted tasks can be viewed if he/she wants but can't be worked on again.\n\n- `teachcode` expects you to have a GitHub account. Make sure that you create one if you don't have one. [Learn more - Github Signup](https://docs.github.com/en/github/getting-started-with-github/signing-up-for-a-new-github-account)\n- Navigate to the directory of your choice and type in `teachcode init`.\n- Choose your track. Currently, we provide two tracks, Python and Javascript\n- Enter your name. We ask for your name mainly for greeting purpose.\n- Enter your GitHub username.\n- Enter your GitHub personal token with repo access. [Learn more - GitHub Personal Token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)\n- Now type in `cd teachcode-solutions`.\n- Type in `teachcode fetchtask`.\n- Hurray :tada: you've got your first task.\n- Type in your solution for the task in the file `task1.py` (opted learning track) using any code editor of choice. We recommend using [VS Code](https://code.visualstudio.com/)\n- Now type in `teachcode submit` to submit your solution.\n- Enter your Git credentials when prompted. [Learn more - Git Credentials](https://docs.github.com/en/github/getting-started-with-github/getting-started-with-git)\n- Fetch the next task with `teachcode fetchtask`.\n\n## Available Commands\n\n| command                   | description                                                                           |\n| ------------------------- | ------------------------------------------------------------------------------------- |\n| teachcode init            | Initializes all the tasks                                                             |\n| teachcode fetchtask [key] | Fetches the task correponding to the key if provided (defaults to the very next task) |\n| teachcode submit          | Submits the current task                                                              |\n| teachcode showkeys        | Lists all the keys associated with the submitted tasks                                |\n\n## Contributing\n\nContributions of any kind are welcomed. Make sure that you go through these [guidelines](https://teachcode.madlabs.xyz/guide/contributing.html).\n\n### How should I write a commit message?\n\nThis project uses [Commitlint](https://github.com/conventional-changelog/commitlint/#what-is-commitlint) to check if the commit messages meet the [conventional commit format](https://www.conventionalcommits.org/en/v1.0.0/).\n\nThe full pattern is:\n\n```sh\ntype(scope?): subject #scope is optional\n\nbody? #body is optional\n\nfooter? #footer is optional\n```\n\nFollowing that pattern, your commit messages should look like these:\n\n```sh\nfeat: activate open collective\n```\n\n```sh\nchore: correct typo\n\nIt should be \"guest\" and not \"gest\"\n```\n\n```sh\nrefactor(cli): drop support for node 6\n\nBREAKING CHANGE: you will need to update your node version to keep using this CLI\nThis closes #123\n```\n\n### How should I name my branches?\n\nPrefix your branch names with `feat/`, `docs/` or `hotfix/` for feature proposals, documentation and bug fixes, respectively.\n\n## License\n\nLicensed under `GNU General Public License V3.0`.\n"
  },
  {
    "path": "__e2e__/cli.test.js",
    "content": "'use strict';\n\nconst test = require('ava');\n\nconst { run } = require('./helpers/test-utils');\n\ntest('supplying an unknown command errors', async t => {\n  const { stderr } = await run(['create'], { reject: false });\n  t.true(stderr.includes('Unknown command create'));\n});\n"
  },
  {
    "path": "__e2e__/commands/fetchtask.test.js",
    "content": "'use strict';\n\nconst path = require('path');\nconst test = require('ava');\nconst fs = require('fs');\n\nconst { createUserConfig, run } = require('../helpers/test-utils');\nconst fileExtensionMap = require('../../src/utils/constants');\n\nconst workspacePath = path.join(__dirname, '..', '..', 'src', 'workspace');\n\n// All files for testing purpose are generated within the teachcode-solutions directory\nconst workDir = path.join(__dirname, 'teachcode-solutions');\n\n// Path to config.json\nconst configFilePath = path.join(workDir, 'config.json');\n\nconst learningTracks = Object.keys(fileExtensionMap);\n\n// Create the teachcode-solutions directory\ntest.before(() => fs.mkdirSync(workDir));\n\n// Cleanup\ntest.after(() => fs.rmdirSync(workDir, { recursive: true }));\n\ntest.serial('no config file in the current path should error', async t => {\n  const { exitCode, stderr } = await run(['fetchtask'], {\n    cwd: workDir,\n    reject: false,\n  });\n\n  // Assertions\n  // Exit code\n  t.is(exitCode, 1);\n\n  // Assert for the expected error message\n  t.is(stderr.trim(), 'Could not find config.json in the current path!');\n});\n\ntest.serial('supplying an invalid key should error', async t => {\n  for (const track of learningTracks) {\n    // Fetch the corresponding file extension\n    const fileExtension = fileExtensionMap[track];\n\n    // Create config.json\n    const userConfig = createUserConfig(track, 6);\n    fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n    const { exitCode, stderr, stdout } = await run(\n      ['fetchtask', 'incorrectTestKey'],\n      {\n        cwd: workDir,\n        reject: false,\n      },\n    );\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 1);\n\n    // The file shouldn't be created\n    t.false(fs.existsSync(path.join(workDir, `task6.${fileExtension}`)));\n\n    // Displays user name and progress information\n    t.false(stdout.includes('User: testConfig'));\n    t.false(stdout.includes('Progress: 6/30'));\n\n    // Assert for the expected error message\n    t.is(stderr.trim(), 'Make sure that you have grabbed the key correctly!');\n  }\n});\n\ntest.serial('should be able to access a completed task', async t => {\n  for (const track of learningTracks) {\n    // Fetch the corresponding file extension\n    const fileExtension = fileExtensionMap[track];\n\n    // Create config.json\n    const userConfig = createUserConfig(track, 6);\n    fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n    const { exitCode, stderr, stdout } = await run(['fetchtask', 'testKey2'], {\n      cwd: workDir,\n    });\n    const tasksDir = track !== 'Python' ? fileExtension : track.toLowerCase();\n    const tasks = require(path.join(workspacePath, tasksDir, 'tasks.json'));\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 0);\n\n    // The file shouldn't be created\n    t.false(fs.existsSync(path.join(workDir, `task6.${fileExtension}`)));\n\n    // Assert for the expected error message\n    t.is(stderr.trim(), 'This task is already completed!');\n\n    // Displays user name and progress information\n    t.true(stdout.includes('User: testConfig'));\n    t.true(stdout.includes('Progress: 6/30'));\n\n    // Displays the second task\n    t.true(stdout.includes(tasks[1].task));\n  }\n});\n\ntest.serial('access the current task with the respective key', async t => {\n  for (const track of learningTracks) {\n    // Fetch the corresponding file extension\n    const fileExtension = fileExtensionMap[track];\n\n    // Create config.json\n    const userConfig = createUserConfig(track, 6);\n    fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n    const { exitCode, stdout } = await run(['fetchtask', 'testKey6'], {\n      cwd: workDir,\n    });\n    const tasksDir = track !== 'Python' ? fileExtension : track.toLowerCase();\n    const tasks = require(path.join(workspacePath, tasksDir, 'tasks.json'));\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 0);\n\n    // Assert for the existence of the solution file\n    t.true(fs.existsSync(path.join(workDir, `task6.${fileExtension}`)));\n\n    // This message shouldn't be displayed\n    t.false(stdout.trim().includes('This task is already completed'));\n\n    // Displays user name and progress information\n    t.true(stdout.includes('User: testConfig'));\n    t.true(stdout.includes('Progress: 6/30'));\n\n    // Displays the sixth task\n    t.true(stdout.includes(tasks[5].task));\n  }\n});\n\ntest.serial('not supplying a key fetches the next task', async t => {\n  for (const track of learningTracks) {\n    // Fetch the corresponding file extension\n    const fileExtension = fileExtensionMap[track];\n\n    // Create config.json\n    const userConfig = createUserConfig(track, 6);\n    fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n    const { exitCode, stdout } = await run(['fetchtask'], { cwd: workDir });\n    const tasksDir = track !== 'Python' ? fileExtension : track.toLowerCase();\n    const tasks = require(path.join(workspacePath, tasksDir, 'tasks.json'));\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 0);\n\n    // Assert for the existence of the solution file\n    t.true(fs.existsSync(path.join(workDir, `task6.${fileExtension}`)));\n\n    // This message shouldn't be displayed\n    t.false(stdout.trim().includes('This task is already completed'));\n\n    // Displays user name and progress information\n    t.true(stdout.includes('User: testConfig'));\n    t.true(stdout.includes('Progress: 6/30'));\n\n    // Displays the sixth task\n    t.true(stdout.includes(tasks[5].task));\n  }\n});\n\ntest.serial(\n  'displays an appropriate message if no more tasks are available',\n  async t => {\n    for (const track of learningTracks) {\n      // Create config.json\n      const userConfig = createUserConfig(track, 30);\n      fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n      const { exitCode, stderr, stdout } = await run(['fetchtask'], {\n        cwd: workDir,\n      });\n\n      // Assertions\n      // Exit code\n      t.is(exitCode, 0);\n\n      // Won't display user name and progress information\n      t.false(stdout.includes('User: testConfig'));\n      t.false(stdout.includes('Progress'));\n\n      // Assert for the expected message\n      t.is(stderr.trim(), 'No more tasks available!');\n    }\n  },\n);\n"
  },
  {
    "path": "__e2e__/commands/init.test.js",
    "content": "'use strict';\n\nconst path = require('path');\nconst test = require('ava');\nconst fs = require('fs');\n\nconst { createUserConfig, run } = require('../helpers/test-utils');\n\n// All files for testing purpose are generated within the teachcode-solutions directory\nconst workDir = path.join(__dirname, 'teachcode-solutions');\n\n// Path to config.json\nconst configFilePath = path.join(workDir, 'config.json');\n\n// Create the teachcode-solutions directory\ntest.before(() => {\n  fs.mkdirSync(workDir);\n  const userConfig = createUserConfig('Python', 6);\n  fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n});\n\n// Cleanup\ntest.after(() => fs.rmdirSync(workDir, { recursive: true }));\n\ntest.serial(\n  'displays an appropriate message if the teachcode-solutions directory exists in path',\n  async t => {\n    const { exitCode, stderr } = await run(['init'], {\n      cwd: __dirname,\n      reject: false,\n    });\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 1);\n\n    // Assert for the expected error message\n    t.true(\n      stderr\n        .trim()\n        .includes(\n          'It seems that there is already a teachcode-solutions directory or config.json file existing in path',\n        ),\n    );\n  },\n);\n\ntest.serial(\n  'displays an appropriate message if the config.json file exists in path',\n  async t => {\n    const { exitCode, stderr } = await run(['init'], {\n      cwd: workDir,\n      reject: false,\n    });\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 1);\n\n    // Assert for the expected error message\n    t.true(\n      stderr\n        .trim()\n        .includes(\n          'It seems that there is already a teachcode-solutions directory or config.json file existing in path',\n        ),\n    );\n  },\n);\n"
  },
  {
    "path": "__e2e__/commands/showkeys.test.js",
    "content": "'use strict';\n\nconst path = require('path');\nconst test = require('ava');\nconst fs = require('fs');\n\nconst { run } = require('../helpers/test-utils');\n\nconst workDir = path.join(__dirname, 'teachcode-solutions');\nconst configFilePath = path.join(workDir, 'config.json');\n\n// Create the teachcode-solutions directory\ntest.before(() => fs.mkdirSync(workDir));\n\n// Cleanup\ntest.after(() => fs.rmdirSync(workDir, { recursive: true }));\n\n// Execute tests serially as we are creating different temp config files for each test\ntest.serial('no config file in the current path should error', async t => {\n  const { exitCode, stderr } = await run(['showkeys'], {\n    cwd: workDir,\n    reject: false,\n  });\n\n  // Assertions\n  // Exit code\n  t.is(exitCode, 1);\n\n  // Assert for the expected error message\n  t.is(stderr.trim(), 'Could not find config.json in the current path!');\n});\n\ntest.serial(\n  'shows up an appropriate message if the user is getting started',\n  async t => {\n    const configWithoutKeys = {\n      userName: 'configWithoutKeys',\n      taskCount: 0,\n      keys: [],\n    };\n\n    // Create config.json\n    fs.writeFileSync(\n      configFilePath,\n      JSON.stringify(configWithoutKeys, null, 2),\n    );\n    const { exitCode, stdout } = await run(['showkeys'], {\n      cwd: workDir,\n    });\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 0);\n\n    // Displays user name and progress information\n    t.true(stdout.includes('User: configWithoutKeys'));\n    t.true(stdout.includes('Progress: 1/30'));\n\n    // Assert for the expected message\n    t.true(\n      stdout\n        .trim()\n        .includes(\n          'Looks like this is your very first task. Type in teachcode fetchtask to get started!',\n        ),\n    );\n  },\n);\n\ntest.serial('displays the respective keys for the submitted tasks', async t => {\n  const configWithMultipleKeys = {\n    userName: 'configWithMultipleKeys',\n    taskCount: 2,\n    keys: ['testkey1', 'testkey2'],\n  };\n\n  // Create config.json\n  fs.writeFileSync(\n    configFilePath,\n    JSON.stringify(configWithMultipleKeys, null, 2),\n  );\n  const { exitCode, stdout } = await run(['showkeys'], { cwd: workDir });\n\n  // Assertions\n  // Exit code\n  t.is(exitCode, 0);\n\n  // Displays completed tasks and the corresponding keys\n  t.true(stdout.includes('Task-1: testkey1'));\n  t.true(stdout.includes('Task-2: testkey2'));\n\n  // Displays user name and progress information\n  t.true(stdout.includes('User: configWithMultipleKeys'));\n  t.true(stdout.includes('Progress: 3/30'));\n});\n"
  },
  {
    "path": "__e2e__/commands/submit.test.js",
    "content": "'use strict';\n\nconst path = require('path');\nconst test = require('ava');\nconst fs = require('fs');\n\n// const workspacePath = path.join(__dirname, '..', '..', 'src', 'workspace');\n\nconst { createUserConfig, run } = require('../helpers/test-utils');\n\n// All files for testing purpose are generated within the teachcode-solutions directory\nconst workDir = path.join(__dirname, 'teachcode-solutions');\n\n// Path to config.json\nconst configFilePath = path.join(workDir, 'config.json');\n\n// Create the teachcode-solutions directory\ntest.before(() => fs.mkdirSync(workDir));\n\n// Cleanup\ntest.after(() => fs.rmdirSync(workDir, { recursive: true }));\n\ntest.serial('no config file in the current path should error', async t => {\n  const { exitCode, stderr } = await run(['submit'], {\n    cwd: workDir,\n    reject: false,\n  });\n\n  // Assertions\n  // Exit code\n  t.is(exitCode, 1);\n\n  // Assert for the expected error message\n  t.is(stderr.trim(), 'Could not find config.json in the current path!');\n});\n\ntest.serial(\n  'displays an appropriate message if the user is just starting out',\n  async t => {\n    // Create config.json\n    const userConfig = createUserConfig('Python', 0, true);\n    fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n    const { exitCode, stdout } = await run(['submit'], {\n      cwd: workDir,\n      reject: false,\n    });\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 0);\n\n    // Assert for the expected error message\n    t.true(\n      stdout.includes(\n        'Please use teachcode fetchtask to fetch your very first task',\n      ),\n    );\n  },\n);\n\ntest.serial(\n  'displays an error message if an empty file is submitted',\n  async t => {\n    // Create config.json\n    const userConfig = createUserConfig('Python', 6, true);\n    fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n    const fileName = 'task6.py';\n    fs.writeFileSync(path.join(workDir, fileName), '');\n\n    const { exitCode, stderr } = await run(['submit'], {\n      cwd: workDir,\n      reject: false,\n    });\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 1);\n\n    // Assert for the expected error message\n    t.is(stderr.trim(), `The file ${fileName} is empty!`);\n  },\n);\n\ntest.serial(\n  'displays an error message if the expected constructs are not used',\n  async t => {\n    // Create config.json\n    const userConfig = createUserConfig('Python', 3, true);\n    fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n    const fileName = 'task3.py';\n    fs.writeFileSync(path.join(workDir, fileName), `print('HELLO WORLD')\\n11`);\n\n    const { exitCode, stderr } = await run(['submit'], {\n      cwd: workDir,\n      reject: false,\n    });\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 1);\n\n    // Assert for the expected error message\n    t.is(\n      stderr.trim(),\n      'Please make sure that you use the required constructs as provided',\n    );\n  },\n);\n\ntest.serial(\n  'displays an error message if there is an issue with the syntax for the submitted file',\n  async t => {\n    // Create config.json\n    const userConfig = createUserConfig('Python', 3, true);\n    fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n    const fileName = 'task3.py';\n    fs.writeFileSync(path.join(workDir, fileName), `//`);\n\n    const { exitCode, stderr } = await run(['submit'], {\n      cwd: workDir,\n      reject: false,\n    });\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 1);\n\n    // Assert for the expected error message\n    t.true(\n      stderr.includes('Oops, there is something wrong with the syntax part!'),\n    );\n  },\n);\n\ntest.serial(\n  'displays an appropriate message if all the tasks are completed',\n  async t => {\n    // Create config.json\n    const userConfig = createUserConfig('Python', 30, true);\n    fs.writeFileSync(configFilePath, JSON.stringify(userConfig, null, 2));\n\n    const { exitCode, stdout } = await run(['submit'], {\n      cwd: workDir,\n      reject: false,\n    });\n\n    // Assertions\n    // Exit code\n    t.is(exitCode, 0);\n\n    // Assert for the expected error message\n    t.true(stdout.trim().includes('All tasks are completed'));\n  },\n);\n"
  },
  {
    "path": "__e2e__/helpers/test-utils.js",
    "content": "const execa = require('execa');\nconst { join } = require('path');\n\nconst fileExtensionMap = require('../../src/utils/constants');\n\nconst CLI_PATH = join(__dirname, '..', '..', 'bin');\n\n// Create config.json for testing purpose\nconst createUserConfig = (trackName, keysCount, isSubmit = false) => {\n  const userConfig = {\n    learningTrack: '',\n    userName: 'testConfig',\n    taskCount: 0,\n    keys: [],\n    userSubmittedFiles: [],\n  };\n  userConfig['learningTrack'] = trackName;\n\n  // Early return to access the defaults\n  if (keysCount === 0) {\n    return userConfig;\n  }\n\n  // For the submit command the keys and submitted files count would be the same\n  const filesCount =\n    keysCount === 30 ? 30 : isSubmit ? keysCount : keysCount - 1;\n\n  for (let i = 0; i < keysCount; i++) {\n    userConfig['keys'].push(`testKey${i + 1}`);\n  }\n  for (let i = 0; i < filesCount; i++) {\n    userConfig['userSubmittedFiles'].push(\n      `task${i + 1}.${fileExtensionMap[trackName]}`,\n    );\n  }\n  userConfig['taskCount'] = keysCount === 30 ? keysCount : keysCount - 1;\n\n  return userConfig;\n};\n\nconst run = (args, options) => execa('node', [CLI_PATH].concat(args), options);\n\nmodule.exports = {\n  createUserConfig,\n  run,\n};\n"
  },
  {
    "path": "bin/index.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nconst chalk = require('chalk');\nconst program = require('commander');\nconst leven = require('leven');\n\nconst { version } = require('../package');\n\nconst logger = require('../src/utils/logger');\n\nconst initTasks = require('../src/commands/init');\nconst fetchTask = require('../src/commands/tasks');\nconst showKeys = require('../src/commands/keys');\nconst submitTask = require('../src/commands/submit');\n\n// Defining all the available commands\nprogram\n  .name('teachcode')\n  .version(version)\n  .usage('<command> [options]');\n\nprogram\n  .command('init')\n  .description('Initialize challenges')\n  .action(initTasks);\n\nprogram\n  .command('submit')\n  .description('Submits current task')\n  .action(submitTask);\n\nprogram\n  .command('fetchtask [key]')\n  .description('Fetch tasks to be worked upon')\n  .action(fetchTask);\n\nprogram\n  .command('showkeys')\n  .description('Shows keys of all the completed tasks')\n  .action(showKeys);\n\nconst suggestCommands = cmd => {\n  const availableCommands = program.commands.map(c => c._name);\n\n  const suggestion = availableCommands.find(c => leven(c, cmd) < 3);\n  if (suggestion) {\n    logger.info(` Did you mean ${chalk.yellow(suggestion)}?`);\n  }\n};\n\n// Validation for unknown commands\nprogram.on('command:*', ([cmd]) => {\n  program.outputHelp();\n  console.log();\n  logger.error(` Unknown command ${chalk.yellow(cmd)}.`);\n  console.log();\n  suggestCommands(cmd);\n});\n\nprogram.parse(process.argv);\n"
  },
  {
    "path": "commitlint.config.js",
    "content": "module.exports = {\n  extends: ['@commitlint/config-conventional'],\n};\n"
  },
  {
    "path": "docs/.vuepress/config.js",
    "content": "\nmodule.exports = {\n    title: 'teachcode',\n    description: 'Learn to code effectively',\n    head: [\n        ['link', { rel: 'icon', href: 'images/logo.png' }]\n    ],\n    themeConfig: {\n    \trepo: 'madlabsinc/teachcode',\n        nav: [\n            {text: 'Home', link: '/'},\n            {text: 'Guide', link: '/guide/'},\n        ],\n        sidebar: {\n            '/guide/': [{\n                title: 'Guide',\n                children: [\n                  'installation',\n                  'commands',\n                  'contributing'\n                ]\n            }],\n        },\n        docsDir: 'docs',\n        editLinks: true,\n    \teditLinkText: 'Edit this page on GitHub'\n    }\n}\n"
  },
  {
    "path": "docs/README.md",
    "content": "---\nhome: true\nheroImage: images/teachcode.png\nactionText: Get Started →\nactionLink: /guide/\nfeatures:\n- title: Learn Effectively\n  details: Solve simple challenges in the end familiarising with a new programming language.\n- title: Resume Anytime\n  details: All completed tasks are pushed to a remote repository which makes it easier to track the user progress.\n- title: Love The Terminal\n  details: Everything happens in the CLI environment which inturn takes away the fear from novices.\nfooter: GPL V3 Licensed | Copyright © 2019-present MadHacks\n---\n"
  },
  {
    "path": "docs/guide/README.md",
    "content": "# teachcode\n\n> Brush up your programming skills right from the terminal.\n\n## How it works\n\nUsers are required to solve 30 tasks that take them through the basic constructs of the programming language of their choice. The tasks are designed in such a way that the complexity increases as users progress through the tasks. One can't move forward until the current task is completed. Previously submitted tasks can be viewed if he/she wants but can't be worked on again.\n\n- `teachcode` expects you to have a GitHub account. Make sure that you create one if that's not the case.\n- Navigate to the directory of your choice and type in `teachcode init`. After typing the command, the following window would appear in your terminal\n\n<br />\n\n![image](https://user-images.githubusercontent.com/59525675/71776957-9b5c5500-2fbf-11ea-93fa-830f0842ac72.png)\n\n<br />\n\n- Select the language of your choice and follow the instructions as prompted.\n\n<br />\n\n![image](https://user-images.githubusercontent.com/43414928/71539868-c82dbe00-2968-11ea-997d-bb1e8ca01295.png)\n\n<br />\n\n- After entering your Github user token, you would get the following screen. Now type in `cd teachcode-solutions` followed by `teachcode fetchtask`.\n\n<br />\n\n- Hurray :tada: , you've got your first task.\n- Now you can find a `config.json` and `task1.py` (language of choice) file within the `teachcode-solutions` directory.\n\n<br />\n\n![image](https://user-images.githubusercontent.com/59525675/71777696-458caa80-2fc9-11ea-9b07-89e6fc9f9432.png)\n\n<br />\n\n- Open up your favorite editor and code up the solution.\n\n<br />\n\n![image](https://user-images.githubusercontent.com/59525675/71777665-065e5980-2fc9-11ea-80d8-a4b34ad8657d.png)\n\n<br />\n\n- Now type in `teachcode submit`.\n- Enter your Git credentials when prompted.\n- If the current solution satisfies all test cases, you'll get the key to proceed farther.\n- Now type in `teachcode fetchtask`.  \n- Solve all 30 question, to complete the task \n\n\n*In case you want to revisit any of the previously submitted tasks, grab the associated key by typing in `teachcode showkeys` followed by `teachcode fetchtask <key>`*\n- That's all folks, good luck :+1:\n\n\n\n"
  },
  {
    "path": "docs/guide/commands.md",
    "content": "---\ntitle: 'Available Commands'\n---\n\n# Available Commands\n\n `teachcode` offers the following set of commands:-\n\n | command | description |                                                                                                \n | -------------- |  ---------------- |\n | teachcode init | Initializes all the tasks |\n | teachcode fetchtask \\[key\\] | Fetches the task correponding to the key if provided (Defaults to the very next task) |\n | teachcode submit | Submits the current task |\n | teachcode showkeys | Lists all the keys associated with the submitted tasks |\n\n## Versioning And Help\n\n| option | description\n| --- | --- |\n| -V, --version | Check CLI version |\n| --help, -h | Get help and check usage |\n"
  },
  {
    "path": "docs/guide/contributing.md",
    "content": "---\ntitle: 'Contributing'\n---\n\n# Contributing\n\n## Guidelines\n\n1. Fork and clone the repository.\n2. Navigate to the project directory.\n3. Now install the dependencies with `npm install`\n4. Type in `npm link` which creates a symlink and thereby allowing `teachcode` to be accessed globally.\n5. Make your life changing changes.\n6. Ensure that your code is free from linting errors and is as per prettier conventions by typing in `npm run lint`.\n7. We use [commitlint conventional naming rules](https://www.npmjs.com/package/@commitlint/config-conventional#rules) for our commits, make sure that you follow them.\n8. Now you may push it to the remote repository by switching over to another branch and finally proposing a Pull Request to the base fork.\n\n\n## Points to ponder\n\n1. Make sure that you submit an issue first if you have something in mind that you're willing to work on.\n2. Follow a `rebase` strategy to update your remote branch with the latest changes.\n3. Prefix your branch names with `feat/`, `docs/` or `hotfix/` for feature proposals, docs-related and bug fixes, respectively.\n"
  },
  {
    "path": "docs/guide/installation.md",
    "content": "---\ntitle: 'Installation'\n---\n\n# Installation\n\n## Prerequisites\n\n- [**npm**](https://www.npmjs.com/) is a package manager for the JavaScript programming language.\n- [**node.js**](https://nodejs.org/en/) is an open-source, cross-platform JavaScript run-time environment that executes JavaScript code outside of a browser.\n- [**git**](https://git-scm.com/) is a version control system for tracking changes in computer files and coordinating work on those files among multiple people. It is primarily used for source code management in software development.\n\n## Quickstart\n\n``` bash\nnpm install -g teach-code\nteachcode init\n```\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"teach-code\",\n  \"version\": \"1.3.2\",\n  \"description\": \"A tool to develop and improve a student’s programming skills by introducing the earliest lessons of coding.\",\n  \"main\": \"./bin/index.js\",\n  \"files\": [\n    \"bin\",\n    \"src\"\n  ],\n  \"bin\": {\n    \"teachcode\": \"./bin/index.js\"\n  },\n  \"scripts\": {\n    \"lint\": \"eslint src bin __e2e__\",\n    \"lint:fix\": \"eslint --fix src bin __e2e__\",\n    \"pretest\": \"npm run lint\",\n    \"test\": \"ava --serial\",\n    \"docs:dev\": \"vuepress dev docs\",\n    \"docs:build\": \"vuepress build docs\"\n  },\n  \"ava\": {\n    \"files\": [\n      \"__e2e__/**/*.test.js\"\n    ]\n  },\n  \"husky\": {\n    \"hooks\": {\n      \"pre-commit\": \"lint-staged\",\n      \"commit-msg\": \"commitlint -E HUSKY_GIT_PARAMS\"\n    }\n  },\n  \"lint-staged\": {\n    \"linters\": {\n      \"src/**/*.js\": \"npm run lint\"\n    }\n  },\n  \"keywords\": [\n    \"node.js\",\n    \"commander.js\",\n    \"inquirer.js\",\n    \"shell.js\",\n    \"cli\",\n    \"python3\"\n  ],\n  \"author\": \"James George <jamesgeorge998001@gmail.com>\",\n  \"bugs\": {\n    \"url\": \"https://github.com/madlabsinc/teach-code/issues\"\n  },\n  \"homepage\": \"https://github.com/madlabsinc/teach-code#readme\",\n  \"license\": \"GPL-3.0\",\n  \"dependencies\": {\n    \"axios\": \"^0.21.1\",\n    \"chalk\": \"^2.4.1\",\n    \"commander\": \"^6.2.0\",\n    \"execa\": \"^4.1.0\",\n    \"inquirer\": \"^6.2.0\",\n    \"leven\": \"^3.1.0\",\n    \"node-banner\": \"^1.3.2\",\n    \"open\": \"^7.0.0\",\n    \"ora\": \"^4.0.3\",\n    \"python-shell\": \"^1.0.7\"\n  },\n  \"devDependencies\": {\n    \"@commitlint/cli\": \"^8.2.0\",\n    \"@commitlint/config-conventional\": \"^8.2.0\",\n    \"ava\": \"^3.13.0\",\n    \"eslint\": \"^5.16.0\",\n    \"eslint-config-prettier\": \"^4.3.0\",\n    \"eslint-plugin-prettier\": \"^3.1.0\",\n    \"husky\": \"^2.7.0\",\n    \"lint-staged\": \"^8.1.7\",\n    \"prettier\": \"^1.17.1\",\n    \"vuepress\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "src/commands/init.js",
    "content": "'use strict';\n\nconst chalk = require('chalk');\nconst fs = require('fs');\nconst inquirer = require('inquirer');\nconst showBanner = require('node-banner');\nconst open = require('open');\nconst ora = require('ora');\n\nconst logger = require('../utils/logger');\n\n// GitHub workflow helpers.\nconst {\n  checkIfRepositoryExists,\n  cloneRepository,\n  createRepository,\n  configureLocalRepo,\n  initializeGHWorkFlow,\n} = require('../utils/github');\n\nconst validate = require('../utils/validate');\n\n// Key for the very first task\nconst key = '5e06b81de9ac43218a974785ffce8146';\n\nlet userConfig = {\n  learningTrack: '',\n  userName: '',\n  taskCount: 0,\n  keys: [],\n  userSubmittedFiles: [],\n};\n\n/**\n * Displays the initial instructions\n *\n * @param {Boolean} kickStart - Identifies if the user is just starting out\n * @returns {Void}\n */\n\nconst showInstructions = () => {\n  console.log();\n  logger.success(' Perform the following steps:-');\n  console.log();\n  logger.info(' 1. cd teachcode-solutions');\n  logger.info(` 2. teachcode fetchtask`);\n};\n\n/**\n * Opens up the default browser with information concerning\n * access token creation as required\n * @returns {Promise<void>}\n */\n\nconst promptAccessTokenCreation = async () => {\n  const instructionsUrl =\n    'https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line';\n\n  console.log();\n  logger.success(\n    'You are required to have a personal access token for consuming the GitHub API.\\nIf you do not have one, please follow these instructions.\\n',\n  );\n\n  const { openInBrowser } = await inquirer.prompt([\n    {\n      name: 'openInBrowser',\n      type: 'confirm',\n      message: 'Open browser to read instructions?',\n    },\n  ]);\n  if (openInBrowser) {\n    // open link in the default browser\n    await open(instructionsUrl);\n  }\n};\n\n/**\n * Initialize all the tasks\n *\n * @returns {Promise<void>}\n */\n\nconst initTasks = async () => {\n  await showBanner(\n    'teachcode',\n    ` Learn to code effectively ${`\\t`.repeat(4)} Powered by MadHacks`,\n  );\n  console.log();\n\n  if (\n    ['./config.json', './teachcode-solutions'].some(path => fs.existsSync(path))\n  ) {\n    console.log();\n    logger.error(\n      `  It seems that there is already a ${chalk.yellow.bold(\n        'teachcode-solutions',\n      )} directory or ${chalk.yellow.bold(\n        'config.json',\n      )} file existing in path`,\n    );\n    process.exit(1);\n  }\n\n  console.log();\n  logger.success(\n    ` Welcome to teachcode${`\\n`.repeat(2)}${`\\t`.repeat(\n      2,\n    )} Points to ponder ${`\\n`.repeat(\n      4,\n    )} 1. The files to submit the solutions are auto-created\\n 2. Please pay attention to the desired output as specified in the task.\\n 3. You have the provision to view previously submitted tasks ${`\\n`.repeat(\n      4,\n    )}`,\n  );\n\n  // Prompt the user to choose between the available learning tracks\n  const { learningTrackOfChoice } = await inquirer.prompt([\n    {\n      name: 'learningTrackOfChoice',\n      type: 'list',\n      message: 'Choose your track',\n      choices: ['Python', 'JavaScript'],\n    },\n  ]);\n\n  // Prompt the user asking for his/her name\n  const { userName } = await inquirer.prompt([\n    {\n      name: 'userName',\n      type: 'input',\n      message: \"What's your name:-\",\n      validate,\n    },\n  ]);\n\n  // Setting up initial user-data config\n  userConfig = {\n    ...userConfig,\n    learningTrack: learningTrackOfChoice,\n    userName,\n  };\n\n  userConfig.keys.push(key);\n\n  // Prompt for GitHub username.\n  await initializeGHWorkFlow();\n\n  // Check if the remote repository already exists.\n  const shouldCreateRepository = await checkIfRepositoryExists();\n\n  if (shouldCreateRepository) {\n    await promptAccessTokenCreation();\n    await createRepository();\n\n    fs.mkdirSync('teachcode-solutions');\n    fs.writeFileSync(\n      'teachcode-solutions/config.json',\n      JSON.stringify(userConfig, null, 2),\n    );\n    await configureLocalRepo();\n  } else {\n    const spinner = ora('Fetching user progress').start();\n    try {\n      // Clone the remote repository\n      await cloneRepository();\n    } catch (err) {\n      spinner.fail('Something went wrong');\n      throw err;\n    }\n    spinner.stop();\n  }\n  showInstructions();\n};\n\nmodule.exports = initTasks;\n"
  },
  {
    "path": "src/commands/keys.js",
    "content": "'use strict';\n\nconst chalk = require('chalk');\nconst fs = require('fs');\nconst showBanner = require('node-banner');\n\nconst logger = require('../utils/logger');\n\n/**\n * Shows a list of keys that the user has hold of\n *\n * @returns {Promise<void>}\n */\n\nconst showKeys = async () => {\n  await showBanner(\n    'teachcode',\n    ` Learn to code effectively ${`\\t`.repeat(4)} Powered by MadHacks`,\n  );\n  console.log();\n\n  if (!fs.existsSync(`./config.json`)) {\n    logger.error(' Could not find config.json in the current path!');\n    console.log();\n    process.exit(1);\n  }\n\n  let userConfig = fs.readFileSync('./config.json', 'utf8');\n  const { keys, userName, taskCount } = JSON.parse(userConfig);\n\n  console.log();\n  logger.success(\n    `User: ${userName}${`\\t`.repeat(6)}Progress: ${taskCount + 1}/30`,\n  );\n\n  if (keys.length === 0) {\n    console.log();\n    logger.info(\n      `  Looks like this is your very first task. Type in ${chalk.yellow.bold(\n        'teachcode fetchtask',\n      )} to get started!`,\n    );\n    console.log();\n  } else {\n    keys.map((key, idx) => {\n      console.log();\n      logger.success(` Task-${idx + 1}: ${key}`);\n    });\n  }\n};\n\nmodule.exports = showKeys;\n"
  },
  {
    "path": "src/commands/submit.js",
    "content": "'use strict';\n\nconst chalk = require('chalk');\nconst { exec } = require('child_process');\nconst fs = require('fs');\nconst { PythonShell } = require('python-shell');\nconst showBanner = require('node-banner');\nconst path = require('path');\n\nconst fileExtensionMap = require('../utils/constants');\nconst logger = require('../utils/logger');\nconst { makeLocalCommit, pushToRemote } = require('../utils/github');\n\nconst keyStore = '123456789abcedefghijklmnopqrstuvwxyz';\n\nlet userConfig = {};\n\n// Generate a random key that maps to a task\nconst generateKey = () => {\n  let key = '';\n  for (let i = 0; i < 36; i++) {\n    key += keyStore.charAt(Math.floor(Math.random() * keyStore.length));\n  }\n  return key;\n};\n\n// Keywords for validating solutions\nconst validationKeys = [\n  'len',\n  '/3',\n  'if',\n  'for',\n  'while',\n  'for',\n  'if',\n  '/3',\n  '/2',\n  'strip',\n  ':',\n  ':',\n  'def',\n  'if',\n  'return',\n  'asctime',\n  'math.sqrt',\n  '[',\n  '[',\n  'append',\n  'else',\n  '{',\n  'except',\n  'return',\n  'range',\n  'for',\n  '%',\n  '[::',\n];\n\n/**\n * Compares the user submitted solution (result) with that of the predefined version\n *\n * @param {String} submittedFileContent - Content of the user submitted file\n * @param {String} solutionFileContent - Predefined solution file content\n * @param {Number} totalTasks - Total number of tasks for the respective learning track\n *\n * @returns {Promise<void>}\n */\n\nconst checkSolution = async (\n  submittedFileContent,\n  solutionFileContent,\n  totalTasks,\n) => {\n  let { learningTrack, taskCount, keys } = userConfig;\n  try {\n    if (submittedFileContent.toString() === solutionFileContent.toString()) {\n      if (taskCount === totalTasks) {\n        logger.info(' Info: No more tasks are available!');\n        process.exit(0);\n      }\n\n      // Updating config.json information.\n      taskCount++;\n\n      // Push a randomly generated key to the keys array\n      keys.push(generateKey());\n\n      userConfig = {\n        ...userConfig,\n        taskCount: Math.min(taskCount, totalTasks),\n        keys,\n      };\n\n      // Write back the updated config\n      fs.writeFileSync('./config.json', JSON.stringify(userConfig, null, 2));\n\n      await makeLocalCommit(taskCount);\n\n      // User is prompted for credentials unless they are valid\n      do {\n        try {\n          await pushToRemote();\n          break;\n        } catch (err) {\n          logger.error('Error: Invalid credentials');\n        }\n      } while (true); // eslint-disable-line\n\n      // Successfully completed the task\n      console.log();\n      logger.success(` Hurray you've done it!`);\n      console.log();\n\n      // All tasks are completed\n      if (taskCount === totalTasks) {\n        logger.info(' Info: No more tasks are available!');\n        process.exit(0);\n      }\n\n      logger.success(\n        `Move to the next task with ${chalk.yellow.bold(\n          'teachcode fetchtask',\n        )}`,\n      );\n    } else {\n      console.log();\n      logger.warn(\n        ` The solution doesn't meet all the output requirements. Please have a look again!`,\n      );\n      console.log();\n    }\n  } catch (err) {\n    console.log();\n    logger.error(\n      ` There is something wrong with task${taskCount + 1}.${\n        fileExtensionMap[learningTrack]\n      }`,\n    );\n  }\n};\n\n/**\n * Validates if the solution meets all the criteria\n *\n * @param {any} solutionFile - User submitted file\n * @returns {Void}\n */\n\nconst validateSolution = solutionFile => {\n  const fileContent = fs.readFileSync(solutionFile, 'utf8').toString();\n  const { learningTrack, taskCount } = userConfig;\n\n  // Validation for the submitted solution\n  if (learningTrack === 'Python') {\n    if (taskCount >= 2) {\n      if (!fileContent.includes(validationKeys[taskCount - 2])) {\n        console.log();\n        logger.error(\n          ' Please make sure that you use the required constructs as provided',\n        );\n        process.exit(1);\n      }\n    }\n  } else {\n    // TODO: Validation for JS solutions\n  }\n};\n\n/**\n * Solution submission logic\n *\n * @returns {Void}\n */\n\nconst submitTask = async () => {\n  await showBanner(\n    'teachcode',\n    ` Learn to code effectively ${`\\t`.repeat(4)} Powered by MadHacks`,\n  );\n  console.log();\n\n  if (!fs.existsSync('./config.json')) {\n    logger.error(' Could not find config.json in the current path!');\n    console.log();\n    process.exit(1);\n  }\n\n  // Read from config.json\n  userConfig = JSON.parse(fs.readFileSync('./config.json', 'utf8'));\n  const { userName, userSubmittedFiles, learningTrack, taskCount } = userConfig;\n\n  const fileExtension = fileExtensionMap[learningTrack];\n  const tasksDir = learningTrack === 'Python' ? 'python' : fileExtension;\n\n  // Path to the tasks and their solutions\n  const workSpacePath = path.join(__dirname, '..', 'workspace', tasksDir);\n  const exercises = require(path.join(workSpacePath, 'tasks'));\n\n  const solutionFile = path.join(\n    workSpacePath,\n    'solutions',\n    `task${taskCount + 1}.${fileExtension}`,\n  );\n\n  if (taskCount !== exercises.length) {\n    console.log();\n    const progressInfo = `${taskCount + 1}/${exercises.length}`;\n    logger.success(\n      `User: ${userName}${`\\t`.repeat(6)}Progress: ${progressInfo}`,\n    );\n  } else {\n    console.log();\n\n    logger.success(` Congrats ${userName} you've made it through!`);\n    console.log();\n\n    logger.success(' All tasks are completed!');\n    console.log();\n    process.exit(0);\n  }\n\n  if (!userSubmittedFiles.length) {\n    console.log();\n    logger.info(\n      ` Please use ${chalk.yellow.bold(\n        'teachcode fetchtask',\n      )} to fetch your very first task`,\n    );\n    process.exit(0);\n  }\n\n  if (taskCount === userSubmittedFiles.length) {\n    console.log();\n    logger.info(' Info: Task already submitted!');\n    console.log();\n    process.exit(0);\n  }\n\n  const submittedFile = userSubmittedFiles.slice(-1).pop();\n  const submittedFileContent = fs\n    .readFileSync(submittedFile, 'utf8')\n    .toString()\n    .split('');\n\n  if (!submittedFileContent.length) {\n    console.log();\n    logger.error(` The file task${taskCount + 1}.${fileExtension} is empty!`);\n    console.log();\n    process.exit(1);\n  }\n\n  if (learningTrack === 'Python') {\n    PythonShell.run(submittedFile, null, (err, result) => {\n      if (err) {\n        console.log();\n        logger.error(' Oops, there is something wrong with the syntax part!');\n        console.log();\n        logger.error(err.toString());\n        process.exit(1);\n      }\n\n      PythonShell.run(solutionFile, null, (err, solution) => {\n        if (err) {\n          logger.error(' ' + err.toString());\n          process.exit(1);\n        }\n\n        if (typeof result === 'undefined' || typeof solution === 'undefined') {\n          console.log();\n          logger.error(\n            ` Please take a look at task${taskCount}.${fileExtension}`,\n          );\n          process.exit(1);\n        }\n        validateSolution(submittedFile);\n        checkSolution(result, solution, exercises.length);\n      });\n    });\n  } else {\n    exec(`node ${submittedFile}`, (err, result) => {\n      if (err) {\n        logger.error(' Oops there is something wrong with the syntax part!');\n        process.exit(1);\n      }\n      exec(`node ${solutionFile}`, (err, solution) => {\n        if (err) throw err;\n        validateSolution(submittedFile);\n        checkSolution(result, solution, exercises.length);\n      });\n    });\n  }\n};\n\nmodule.exports = submitTask;\n"
  },
  {
    "path": "src/commands/tasks.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst showBanner = require('node-banner');\n\nconst fileExtensionMap = require('../utils/constants');\nconst logger = require('../utils/logger');\n\n/**\n * Fetch the respective task corresponding to the supplied key\n *\n * @param {String} key - key that corresponds to a task\n * @returns {Promise<void>}\n */\n\nconst fetchTask = async key => {\n  await showBanner(\n    'teachcode',\n    ` Learn to code effectively ${`\\t`.repeat(4)} Powered by MadHacks`,\n  );\n  console.log();\n\n  if (!fs.existsSync('./config.json')) {\n    logger.error(' Could not find config.json in the current path!');\n    console.log();\n    logger.info(\n      ' Make sure that you are within the teachcode-solutions directory!',\n    );\n    console.log();\n    process.exit(1);\n  }\n\n  // Reading the user-config information.\n  const userConfig = JSON.parse(fs.readFileSync('./config.json', 'utf8'));\n\n  const {\n    learningTrack,\n    userName,\n    taskCount,\n    keys,\n    userSubmittedFiles,\n  } = userConfig;\n\n  // For eg: task1.py\n  const fileName = `task${taskCount + 1}.${fileExtensionMap[learningTrack]}`;\n\n  const tasksDir =\n    learningTrack === 'Python' ? 'python' : fileExtensionMap[learningTrack];\n  const exercises = require(path.join(\n    __dirname,\n    '..',\n    'workspace',\n    tasksDir,\n    'tasks',\n  ));\n\n  // Progress information\n  const progressInfo = `${Math.min(taskCount + 1, 30)}/${exercises.length}`;\n\n  if (key && !keys.includes(key)) {\n    console.log();\n    logger.error('Make sure that you have grabbed the key correctly!');\n    console.log();\n    process.exit(1);\n  }\n\n  // Check if no more tasks are available (no key provided)\n  if (!key && taskCount === exercises.length) {\n    console.log();\n    logger.warn(' No more tasks available!');\n    process.exit(0);\n  }\n\n  // In case no key is provided, fetch the next task\n  if (!key) {\n    key = keys.slice(-1).pop();\n  }\n\n  // Fetch the key position within the user config if it is not the current task\n  const taskIdx = keys.slice(0, taskCount).indexOf(key);\n\n  if (taskIdx !== -1) {\n    console.log();\n    logger.warn(' This task is already completed!');\n\n    console.log();\n    console.log();\n\n    // Display user name and progress information\n    logger.success(\n      `User: ${userName}${`\\t`.repeat(4)}Progress: ${progressInfo}`,\n    );\n    console.log();\n\n    // Display the task corresponding to the key supplied\n    logger.success(exercises[taskIdx].task);\n    console.log();\n    return;\n  }\n\n  // Grab the key corresponding to the most recent task\n  if (keys.slice(-1).pop() === key) {\n    if (!userSubmittedFiles.includes(fileName)) {\n      userSubmittedFiles.push(fileName);\n    }\n\n    // Write back the updated config\n    fs.writeFileSync('./config.json', JSON.stringify(userConfig, null, 2));\n\n    // Display user name and progress information\n    console.log();\n    logger.success(\n      `User: ${userName}${`\\t`.repeat(6)}Progress: ${progressInfo}`,\n    );\n\n    // Display the task\n    console.log();\n    logger.success(exercises[taskCount].task);\n    console.log();\n\n    // Create a file to submit the solution corresponding to the current task\n    const commentChar = learningTrack === 'Python' ? '#' : '//';\n    fs.writeFileSync(\n      fileName,\n      `${commentChar} Write your solution in this file`,\n    );\n  }\n};\n\nmodule.exports = fetchTask;\n"
  },
  {
    "path": "src/utils/constants.js",
    "content": "'use strict';\n\n// Holds a reference to the file extensions corresponding to the learning track\nconst fileExtensionMap = {\n  Python: 'py',\n  JavaScript: 'js',\n};\n\nmodule.exports = fileExtensionMap;\n"
  },
  {
    "path": "src/utils/github.js",
    "content": "'use strict';\n\nconst axios = require('axios');\nconst chalk = require('chalk');\nconst execa = require('execa');\nconst inquirer = require('inquirer');\n\nconst validate = require('./validate');\n\n// Global reference to the GitHub username.\nlet GHUserName;\n\n/**\n * Initial Git workflow\n *\n * @returns {Promise<void>}\n */\n\nconst initializeGHWorkFlow = async () => {\n  const { userName } = await inquirer.prompt({\n    name: 'userName',\n    message: 'GitHub username:-',\n    type: 'input',\n    validate,\n  });\n\n  // Holding global reference to the GitHub username.\n  GHUserName = userName;\n\n  // Check if it is a valid username\n  if (!(await checkIfValidUser())) {\n    console.log();\n    console.log(chalk.red.bold(` ${userName} isn't a valid GitHub username`));\n    console.log();\n    await initializeGHWorkFlow();\n  }\n};\n\n/**\n * Checks if the remote repository exists\n *\n * @returns {Promise<boolean>}\n */\n\nconst checkIfValidUser = async () => {\n  const API_URL = `https://api.github.com/users/${GHUserName}`;\n  try {\n    await axios.get(API_URL);\n    return true;\n  } catch (err) {\n    return false;\n  }\n};\n\n/**\n * Checks if the remote repository exists\n *\n * @returns {Promise<boolean>}\n */\n\nconst checkIfRepositoryExists = async () => {\n  const API_URL = `https://api.github.com/repos/${GHUserName}/teachcode-solutions`;\n\n  // Checking whether the remote repository exists.\n  try {\n    await axios.get(API_URL);\n    return false;\n  } catch (err) {\n    // Repository should be created.\n    return true;\n  }\n};\n\n/**\n * Clone a remote repository to the local machine\n *\n * @returns {Promise<void>}\n */\n\nconst cloneRepository = async () => {\n  const repoUrl = `https://github.com/${GHUserName}/teachcode-solutions`;\n  await execa.command(`git clone ${repoUrl}`);\n};\n\n/**\n * Create a remote repository\n *\n * @returns {Promise<void>}\n */\n\nconst createRepository = async () => {\n  const { userToken } = await inquirer.prompt({\n    name: 'userToken',\n    message: 'GitHub user token:-',\n    type: 'password',\n    validate,\n  });\n\n  const API_URL = `https://api.github.com/user/repos`;\n  axios.defaults.headers.common['Authorization'] = `token ${userToken}`;\n  // Create a new repository.\n  try {\n    await axios.post(API_URL, { name: 'teachcode-solutions' });\n  } catch (err) {\n    console.log(chalk.red.bold('Error: Invalid credentials'));\n    console.log();\n    await createRepository();\n  }\n};\n/**\n * Configure local repository\n *\n * @returns {Promise<void>}\n */\n\nconst configureLocalRepo = async () => {\n  const repoUrl = `https://github.com/${GHUserName}/teachcode-solutions`;\n\n  // Initialize an empty git repo.\n  await execa.command('git init', { cwd: 'teachcode-solutions' });\n\n  // Set the remote url.\n  await execa.command(`git remote add origin ${repoUrl}`, {\n    cwd: 'teachcode-solutions',\n  });\n};\n\n/**\n * Creates a local commit on each submission\n *\n * @param {Number} taskCount - Holds the present task count\n * @returns {Promise<void>}\n */\n\nconst makeLocalCommit = async taskCount => {\n  await execa.command('git add .');\n  await execa.command(`git commit -m \"solution for task-${taskCount}\"`);\n};\n\n/**\n * Push to the remote repository once the current task was successfully completed\n *\n * @returns {Promise<void>}\n */\n\nconst pushToRemote = async () => {\n  console.log();\n  await execa.command('git push origin master', { stdio: 'inherit' });\n};\n\nmodule.exports = {\n  checkIfRepositoryExists,\n  cloneRepository,\n  configureLocalRepo,\n  createRepository,\n  initializeGHWorkFlow,\n  makeLocalCommit,\n  pushToRemote,\n};\n"
  },
  {
    "path": "src/utils/logger.js",
    "content": "'use strict';\n\nconst chalk = require('chalk');\n\nconst error = msg => console.error(chalk.red.bold(msg));\n\nconst info = msg => console.info(chalk.cyan.bold(msg));\n\nconst success = msg => console.log(chalk.green.bold(msg));\n\nconst warn = msg => console.warn(chalk.yellow.bold(msg));\n\nmodule.exports = {\n  error,\n  info,\n  success,\n  warn,\n};\n"
  },
  {
    "path": "src/utils/validate.js",
    "content": "'use strict';\n\n/**\n * Validate user input\n *\n * @param {String} userInput\n * @returns {Boolean}\n */\n\nconst validateInput = userInput => {\n  if (!userInput) {\n    console.log('This field is required!');\n    return false;\n  }\n  return true;\n};\n\nmodule.exports = validateInput;\n"
  },
  {
    "path": "src/workspace/js/solutions/task1.js",
    "content": "console.log('Hello World');\n"
  },
  {
    "path": "src/workspace/js/solutions/task10.js",
    "content": "let s = 1;\ndo {\n  if (s % 2 === 0) {\n    console.log(s + ' is even.');\n  } else {\n    console.log(s + ' is odd.');\n  }\n  s++;\n} while (s <= 20);\n"
  },
  {
    "path": "src/workspace/js/solutions/task11.js",
    "content": "let i = 1;\nwhile (i <= 15) {\n  if (i % 3 === 0) {\n    i++;\n    continue;\n  } else if (i === 13) {\n    break;\n  } else {\n    console.log(i);\n  }\n  i++;\n}\n"
  },
  {
    "path": "src/workspace/js/solutions/task12.js",
    "content": "let no = [45, 23, 767, 921];\n\nfor (let i = 0; i < no.length; i++) {\n  if (no[i] > 23) console.log(no[i]);\n}\n"
  },
  {
    "path": "src/workspace/js/solutions/task13.js",
    "content": "let a = ['ABC', 'GHI', 'DEF', 'JKL'];\nlet b = [1, 2, 3];\na.pop();\nconsole.log(a);\na.push('PQR');\nconsole.log(a);\na.shift();\nconsole.log(a);\na.splice(1, 2, 'WER', 'ERT');\nconsole.log(a);\na = a.concat(b);\nconsole.log(a);\na.sort();\nconsole.log(a);\na.reverse();\nconsole.log(a);\nlet c = b.map(element => {\n  return 2 * element;\n});\nconsole.log(c);\n"
  },
  {
    "path": "src/workspace/js/solutions/task14.js",
    "content": "function add(a, b) {\n  console.log(a + b);\n}\nadd(1, 2);\nadd(10, 15);\nadd(100, 400);\n"
  },
  {
    "path": "src/workspace/js/solutions/task15.js",
    "content": "let person = {\n  age: 75,\n  gender: 'female',\n};\n\nlet yyyy = 2019 - person.age;\nconsole.log(yyyy);\nconsole.log(person.gender);\n"
  },
  {
    "path": "src/workspace/js/solutions/task16.js",
    "content": "console.log(Math.round(5.57));\nconsole.log(Math.pow(6, 3));\nconsole.log(Math.sqrt(841));\nconsole.log(Math.ceil(5.3));\nconsole.log(Math.floor(5.3));\n"
  },
  {
    "path": "src/workspace/js/solutions/task17.js",
    "content": "let day;\nswitch (new Date().getDay()) {\n  case 0:\n    day = 'Sunday';\n    break;\n  case 1:\n    day = 'Monday';\n    break;\n  case 2:\n    day = 'Tuesday';\n    break;\n  case 3:\n    day = 'Wednesday';\n    break;\n  case 4:\n    day = 'Thursday';\n    break;\n  case 5:\n    day = 'Friday';\n    break;\n  case 6:\n    day = 'Saturday';\n}\nconsole.log(day);\n"
  },
  {
    "path": "src/workspace/js/solutions/task18.js",
    "content": "let a = true.toString();\nlet b = false.toString();\nconsole.log(typeof a);\nconsole.log(typeof b);\nlet c = true;\nlet d = false;\nconsole.log(typeof c);\nconsole.log(typeof d);\n"
  },
  {
    "path": "src/workspace/js/solutions/task19.js",
    "content": "let a = 10;\nfunction abc() {\n  let a = 4;\n  console.log(a);\n}\n\nabc();\nconsole.log(a);\n"
  },
  {
    "path": "src/workspace/js/solutions/task2.js",
    "content": "const str = 18;\nconsole.log(str);\n"
  },
  {
    "path": "src/workspace/js/solutions/task20.js",
    "content": "const pounds = [11.21, 19.21, 46.21];\n\nconst sum = pounds.reduce((total, amount) => total + amount);\n\nconsole.log(sum);\n"
  },
  {
    "path": "src/workspace/js/solutions/task21.js",
    "content": "const numbers = [1, 3, 4, 6, 8, 9];\n\nconst filterValues = () => {\n  return numbers.filter(number => {\n    return number % 2 === 0;\n  });\n};\n\nconsole.log(filterValues());\n"
  },
  {
    "path": "src/workspace/js/solutions/task22.js",
    "content": "let a = [3, 9, 12, 15, 18];\nconsole.log(a.indexOf(15, 2));\nconsole.log(a.indexOf(14, 1));\n"
  },
  {
    "path": "src/workspace/js/solutions/task23.js",
    "content": "let obj = {\n  name: 'ABC',\n  education: 'CSE',\n};\nconsole.log(Object.keys(obj));\nlet arr = ['A', 'B', 'C'];\nconsole.log(Object.keys(arr));\n"
  },
  {
    "path": "src/workspace/js/solutions/task24.js",
    "content": "let text = '{ \"name\":\"John\", \"age\":\"39\", \"city\":\"New York\"}';\nlet obj = JSON.parse(text, function(key, value) {\n  if (key === 'city') {\n    return value.toUpperCase();\n  } else {\n    return value;\n  }\n});\n\nconsole.log(obj);\n"
  },
  {
    "path": "src/workspace/js/solutions/task25.js",
    "content": "console.log(JSON.stringify({ x: 5, y: 6 }));\n"
  },
  {
    "path": "src/workspace/js/solutions/task26.js",
    "content": "let goals = ['Mission', 'Vision', 'Dedication'];\nconsole.log(goals.includes('Mission'));\nconsole.log(goals.includes('Success'));\n"
  },
  {
    "path": "src/workspace/js/solutions/task27.js",
    "content": "const array1 = ['abc', 'bcd', 'cde'];\n\narray1.forEach(item => console.log(item));\nfor (const element of array1) {\n  console.log(element);\n}\nfor (const index in array1) {\n  console.log(index);\n}\n"
  },
  {
    "path": "src/workspace/js/solutions/task28.js",
    "content": "let str = 'JS is AWESOME!';\nlet arr = str.split(' ');\nconsole.log(arr);\nlet a = ['I', 'love', 'JS!'];\nlet s = a.join(' ');\nconsole.log(s);\n"
  },
  {
    "path": "src/workspace/js/solutions/task29.js",
    "content": "let str = 'Hello, I am a novice JS Developer.';\nconsole.log(str.startsWith('Hello'));\nconsole.log(str.endsWith('Develop'));\nlet str1 = 'I am a Polyglot';\nconsole.log(str1.substr(str1.indexOf('P'), str1.indexOf('t')));\nconsole.log(str1.substring(str1.indexOf('a'), str1.indexOf('t') + 1));\n"
  },
  {
    "path": "src/workspace/js/solutions/task3.js",
    "content": "const str = 'JS is cool!';\nconsole.log(str);\n"
  },
  {
    "path": "src/workspace/js/solutions/task30.js",
    "content": "let counter = 0;\n\nconst startCounter = () => {\n  counter++;\n  process.stdout.write(`${counter} `);\n};\n\nconst interval = setInterval(startCounter, 1000);\n\nsetTimeout(() => clearInterval(interval), 6000);\n"
  },
  {
    "path": "src/workspace/js/solutions/task4.js",
    "content": "const str = ' Hey, this is Task 4 of JS Path! ';\nconsole.log(str.length);\nconsole.log(str.indexOf('Task'));\nconsole.log(str.slice(24, 26));\nlet str1 = str.replace('JS', 'Python');\nconsole.log(str1);\nstr1 = str1.concat('!');\nconsole.log(str1);\nconsole.log(str1.trim());\n"
  },
  {
    "path": "src/workspace/js/solutions/task5.js",
    "content": "const a = 25;\nconst b = 33;\nconsole.log(a + b);\nconsole.log(a - b);\nconsole.log(a * b);\nconsole.log(a / b);\nconsole.log(a % b);\nconsole.log(a ** 2);\n"
  },
  {
    "path": "src/workspace/js/solutions/task6.js",
    "content": "const a = 44;\nconst b = 29;\n// eslint-disable-next-line eqeqeq\nconsole.log(a == b);\nconsole.log(a === b);\nconsole.log(a !== b);\nconsole.log(a > b);\nconsole.log(a < b);\nconsole.log(a >= b);\nconsole.log(a <= b);\n"
  },
  {
    "path": "src/workspace/js/solutions/task7.js",
    "content": "const a = 34;\nconst b = 23;\nconst c = 1;\nconsole.log(a > b && a < c);\nconsole.log(a < b || a > c);\nconsole.log(!(b < a));\n"
  },
  {
    "path": "src/workspace/js/solutions/task8.js",
    "content": "for (let i = 1; i <= 12; i++) {\n  if (i % 4 === 0) {\n    console.log(i);\n  }\n}\n"
  },
  {
    "path": "src/workspace/js/solutions/task9.js",
    "content": "let x = 1;\nwhile (x <= 50) {\n  if (x % 5 === 0) {\n    console.log('Buzz');\n  } else {\n    console.log(x);\n  }\n  x++;\n}\n"
  },
  {
    "path": "src/workspace/js/tasks.json",
    "content": "[\n  {\n    \"task\": \"Hey there folks, you have chosen JS Path! \\n Here's your first task! All the best...\\n Task 1:-\\n Print Hello World to the console\"\n  },\n  {\n    \"task\": \"Great! Now's let's move on to variables. Variables are used to store data values \\n Task 2:-\\n Declare a variable to store the value 18 and print the value.\"\n  },\n  {\n    \"task\": \"Let's move on to strings. Strings represent a set of characters written within quotes. \\n Task 3:-\\n Declare a variable to store the value 'JS is cool!' and print it.\"\n  },\n  {\n    \"task\": \"Keep it up! Let's move on to String methods. There are a variety of methods for string manipulation in JS. Some of them are: \\n 1. length - To find the length of the string. \\n 2. indexOf() - Returns the first occurence of a specified text in a string. \\n 3. slice() - extracts a part of a string and returns the extracted part. \\n 4. replace() - replaces a specified value with another value in a string. \\n 5. concat() - to join two or more strings. \\n 6. trim() - removes the white space from both sides of the string. \\n Task 4:-\\n Obtain the following output for the string ' Hey, this is Task 4 of JS Path! ' \\n Output: \\n Length of the string \\n Display the index of first occurence of 'Task' \\n Slice the string for displaying 'JS' \\n Replace JS with Python \\n Concatenate '!' to the end of the string. \\n Remove the whitespaces from the beginning and end of the string.\"\n  },\n  {\n    \"task\": \"Impressive! Let's move on to the next topic:  Operators. \\n There are a variety of operators. Let's move on to Arithmetic Operators: +,-,*,/,%, **. \\n Here's your task:\\n Task 5:- \\n Take 25 & 33 as your operands and print their sum, difference, product, quotient, remainder, 25^2.\"\n  },\n  {\n    \"task\": \"Awesome! Let's move on to Comparison Operators. They are used to compare two values. They return true or false according to the value of their operands. They are: ==, ===, !=, >, <, >=, <=. Here's your task:\\n Task 6:-\\n Use 44 & 29 as your operands. Compare them using the Comparison operators in the same order and print the value which they return.\"\n  },\n  {\n    \"task\": \"Now, let's move on to Logical Operators. They too return true or false according to the value of their operands. They are : \\n && - returns true if both operands are true \\n || - returns true if any of the operands are true \\n ! - negates whatever the statement inside is. \\n Here's your task: \\n Task 7:- \\n Use 34,23,1 as your operands. Check whether\\n 1. 34>23 and 34<1 \\n 2. 34<23 or 34>1 \\n 3. not 23<34\"\n  },\n  {\n    \"task\": \"Great! Let's move on to Loops now. Loops are used to repeat the same code without writing it over and over again. \\n Let's start with for loop. Syntax: \\n for (initialization; condition; update)\\n{// code block to be executed} \\n Here's your task: \\n Task 8:- \\n Print the multiples of 4 from 1 to 12 using for loop.\"\n  },\n  {\n    \"task\": \"Let's move on to another loop, the while loop, along with the if-else blocks. while loop is also an entry controlled loop, i.e, it checks the condition first before it starts executing. If-else blocks are used to compare the values and execute according to the conditions given. \\n Syntax: \\n while(condition) \\n {block of statements; update statement;} \\n Here's your task: \\n Task 9:- \\n Print the numbers from 1 to 50. Print Buzz if the number is a multiple of 5.\"\n  },\n  {\n    \"task\": \"Great work! Let's move on to another loop, the do while loop. Unlike other loops, this one is an exit controlled loop, i.e, it executes at least once. It checks the condition only at the exit. \\n Syntax: do{\\n loop block\\n}(while(condition)); \\n Here's your task: \\nTask 10:-\\n Iterate through the numbers 1 to 20 and print whether the number is odd or even. \\n Here's the sample output: \\n 1 is odd. \\n2 is even. ....\\n20 is even.\"\n  },\n  {\n    \"task\": \"Awesome! Let's now move on to break and continue statements. \\n break statement is used to break out of the loop when required. It stops the iteration when used in loops. \\n continue statments are used to skip the current iteration. \\n The difference between these statements is that in the case of break statement, the iteration stops and breaks out of loop, whereas, in the case of continue, the iteration is skipped but the loop continues to execute. \\n Here's your task: \\n Task 11:- \\n Print numbers from 1 to 15. Skip the iteration if the number is a multiple of 3 and break out of the loop when it reaches 13.\"\n  },\n  {\n    \"task\": \"Fantastic! Now let's move on to arrays. \\n Arrays are used to store multiple values in a single variable. It can be thought of as a collection of things of the same type. Like, a collection of roll numbers. \\n Arrays are declared using []. Eg: let rollno = [1,2,3] \\n Here's your task: \\n Task 13 \\n Store the values 45,23,767,921 into an array and print the values of the array which are greater than 23. Use arrayname.length to get the length of the array.\"\n  },\n  {\n    \"task\": \"Now, let's move on to array methods. \\n Arrays have a variety of methods which is of a lot of help in day-to-day tasks. \\n Let's get to know them: 1. pop() - Used to remove the last item from the array. \\n 2. push() - Used to insert an element to the end of the array. \\n 3. shift() - Used to remove the first item from the array. \\n 4. splice() - Used to replace the old elements with new elements to the array. \\n 5. concat() - to merge two arrays. \\n 6. sort() - to sort an array \\n 7. reverse() - to reverse an array. \\n 8. map() - creates a new array by performing a function on each element. \\n Phew! That's a lot of methods. Let's now work with each of them with the help of this task. \\n Task 14 \\n Create an array with the values ABC, GHI, DEF and JKL. Do the following. 1. Remove JKL from the array.\\n 2. Insert PQR into the array. \\n 3. Remove ABC from the array. \\n 4. Replace the values DEF and PQR with WER and ERT \\n 5. Create another array with values 1,2,3 and merge it with the current array. \\n 6. Sort the array. \\n 7. Reverse the order of elements of the array. \\n 8. Create another array with elements of the second array with elements doubled and print the newly created array. \\n Print the output in every case.\"\n  },\n  {\n    \"task\": \"Keep up the good work! The next topic we will cover is functions. Functions are sections of code that execute other code and make it reusable. \\nIn ES6 there are 2 main ways to declare a function, the function keyword and arrow functions.\\n Syntax: function name(params) {\\n   code\\n} \\nTask 12: Declare a function using the respective keyword that when given 2 numbers will add them together, then print out the result. The number pairs you need to test are 1+2, 10+15, 100+400\"\n  },\n  {\n    \"task\": \"Fantastic! Let's now move on to objects. \\n Objects are similar to variables except that they can take multiple values at a time. The values are written as name:value pairs. \\n For eg: var car = {type:'Fiat', model:'500', color:'white'} \\n Here's your task: \\n Task 15 \\n Create an object person with age: 75 and gender: female. Print the year of birth with the help of her age along with her gender.\"\n  },\n  {\n    \"task\": \"Now's let's learn about another object called the Math object. It allows you to perform mathematical operations. \\n 1. Math.round() - Returns the nearest integer value by rounding off. \\n 2. Math.pow(x,y) - Returns the power of x to the value y. \\n 3. Math.sqrt() - Returns the square root. \\n 4. Math.random() - Returns a random value between 0 and 1. \\n 5. Math.ceil() - Returns the value rounded up to the nearest integer. \\n 6. Math.floor() - Returns the value rounded down to the nearest integer. \\n Here's your task: \\n Task 16 \\n 1. Print the rounded value of 5.57. \\n 2. Find the value of 6^3 and print it. \\n 3. Find the square root of 841. \\n 4. Print the rounded up value of 5.3 \\n 5. Print the rounded down value of 5.3\"\n  },\n  {\n    \"task\": \"Awesome! Let's now move on to switch statement. The switch statement is used to perform different operations based on different inputs. \\n Syntax: \\n switch(variable) { \\n case 1: \\n do something \\n break; \\n case 2: \\n do something else \\n break; .... \\n default: \\n Print invalid choice \\n} \\n Here's your task: \\n Task 17 \\n Receive the current day as a number using the Date.getDay() which returns the values 0-6 (0 - Sunday, 1 - Monday, etc). Based on the value received, print the day on the basis of the value returned. Use switch statement.\"\n  },\n  {\n    \"task\": \"Impressive! Let's now move on to Type Conversion. \\n Variables can be converted to other datatypes using the in-built function or is converted automatically by JS. \\n Here's your task: \\n Task 18 \\n Convert the boolean values true and false to string and print their type using the typeof function. Now store true and false in other variables and print their type. Note the difference in types.\"\n  },\n  {\n    \"task\": \"Awesome! Let's understand scope of a variable. \\n Scopes define the value of the variable according to which it is defined. It can be of global or local scope.\\n Global scope means that the variable can be accessed from any block of the program. Local scope means that the variable can only be accessed by the block in which it is declared in. \\n To illustrate this, let's do the next task. \\n Task 19 \\n Declare a variable inside a function and set a value 4 to it and print it inside the function. Declare the variable with the same name outside the function block with the value 10 and print it there. \\n Note the different values of the same variable printed based on its scope.\"\n  },\n  {\n    \"task\": \"Now, let's move on to Javascript reduce method. \\n The reduce() is used to apply a function to each element in the array to reduce the array to a single value. \\n Let's now find the sum of elements of an array without using the loops. This can be done using the reduce() method. \\n Syntax: array.reduce(function(total, currentValue, currentIndex, arr), initialValue) \\n Here's your task: \\n Task 20 \\n Find the sum of elements of an array with values 11.21, 19.21, 46.21. Do not use any loops. Use reduce().\"\n  },\n  {\n    \"task\": \"Fantastic! Let's now move on to Javascript filter() method. \\n The name itself describes it's purpose. It is used to filter elements of the array according to a particular condition. \\n Syntax: let newArray = array.filter(function(item) { \\n return condition;\\n });\\n Task 21 \\n Use the filter() to find the values of the array containing values 1,3,4,6,8,9 that are divisible by 3 and print the values as output. Do not use any loops or if statements to find the solution. Use filter function only.\"\n  },\n  {\n    \"task\": \"Impressive! Let's move on to some other array method, the indexOf() method. \\n This method searches for the given element from the given starting index and returns the index of the element if found or -1 if not found. \\n Syntax: array.indexOf(item, start) \\n Here's your task: \\n Task 22 \\n Store values 3,9,12,15,18 into an array and search for the element 15 starting from index 2 and then print its index. Then search for 14 starting from index 1 and print the value returned.\"\n  },\n  {\n    \"task\": \"Great work! Let's now learn about keys() method. This is used for returning properties of an object or an array. \\n This method returns values that are keys of the key value pair stored. \\n Syntax: Object.keys(obj) \\n Here's your task: \\n Task 23 \\n Create an object with key-value pairs \\n name: 'ABC', education: 'CSE' and print the values of the keys of the object. \\n Also define an array with values A,B,C. Use keys() to obtain the properties of that array and print them.\"\n  },\n  {\n    \"task\": \"Now let's move on to JSON methods. The first one is JSON.parse(). It is used to parse a string written in JSON format and return a JavaScript object. \\n Syntax: JSON.parse(string, function) \\n Here's your task: \\n Task 24 \\n Create a JSON object\\n var text = '{ 'name':'John', 'age':'39', 'city':'New York'}';\\n Use the parse() to replace the value of city with Capital Case.\"\n  },\n  {\n    \"task\": \"Great! The second one is JSON.stringify(). This method is used to convert JS Objects into strings. \\n Syntax: JSON.stringify(obj, replacer, space) \\n Here's your task: \\n Task 25 \\n Create an object {x: 5, y: 6} and convert it into a string using stringify() and print the returned value.\"\n  },\n  {\n    \"task\": \"Awesome! Let's now move on to includes() method. This is used to check whether if an element is present in an array or a string. \\n Task 26 \\n Create an array with elements Mission, Vision, & Dedication. Search the array for the elements Mission & Success. Print the value returned. Note that it is CASE SENSITIVE.\"\n  },\n  {\n    \"task\": \"Fantastic! Here are some extras! Let's learn for of loop & foreach loop. \\n We had learned for in loop before.\\n foreach is an method that is available only in Array objects. It allows you to iterate through elements of an array. \\n for of is a new way for iterating collections. Its introduced in ES6.\\n For for of to work on an collection, the collection must have an [Symbol.iterator] property.\\n Here's your task: \\n Task 27 \\n Create an array with elements abc,bcd,def. Loop through it using foreach, for of, for in loops. \\n Note the difference in output.\"\n  },\n  {\n    \"task\": \"Amazing! Let's now move on to split() and join() methods. \\n split() is used to split the string into an array by specifying a delimiter. \\n join() is used to join the array elements into a string based on a delimiter. \\n Here's your task: \\n Task 28 \\n Create a variable with the string JS is AWESOME! and split it on the basis of blank spaces. \\n Print the splitted array elements. \\n Then create another array with element , I, love, JS! and convert it into a string and print it.\"\n  },\n  {\n    \"task\": \"Great! Let's now move on to some more String Manipulation methods. \\n startsWith(), endsWith(), substring(), substr()\\n startsWith is used to check whether the string starts with a particular substring or not \\n endsWith is used to check whether the string ends with a particular substring or not. \\n substring is used to extract a particular part of a string. \\n substr is also used to extract a particular part of the string except that it prints including the end index element. \\n Here's your task: \\n Task 29 \\n Initialize a variable with the string Hello, I am a novice JS Developer. and check whether the string starts with Hello and whether it ends with Develop. Print the output. Then initialize another string with the value I am a Polyglot and extract the word Polyglot and print it. Then extract -  am a Polyglot and print it. Use substring() and substr() to obtain the output.\"\n  },\n  {\n    \"task\": \"Congrats! You have made it to the last task! \\n Here's the task: \\n Task 30 \\n Use setInterval(), clearInterval(), and setTimeout() to print the values 1 to 5 with an interval from 1000 to 6000.\"\n  }\n]"
  },
  {
    "path": "src/workspace/python/solutions/task1.py",
    "content": "print('Hello World')\n"
  },
  {
    "path": "src/workspace/python/solutions/task10.py",
    "content": "a = 60\nb = 100\nc = 200\navg = ((a+b+c)/3)\nprint(int(avg))\n"
  },
  {
    "path": "src/workspace/python/solutions/task11.py",
    "content": "a = 10\nb = 12.506\nsum = a+b\navg = sum/2\nprint(sum)\nprint(avg)\n"
  },
  {
    "path": "src/workspace/python/solutions/task12.py",
    "content": "str = ' This is Cool!'\nprint(str.strip())\nprint(len(str))\nprint(str.lower())\nprint(str.upper())\nprint(str.replace(\"T\",\"t\"))\n"
  },
  {
    "path": "src/workspace/python/solutions/task13.py",
    "content": "str = 'Friday'\nprint(str[3:7])\n"
  },
  {
    "path": "src/workspace/python/solutions/task14.py",
    "content": "str = 'AJCE'\nprint(str[::-1])\n"
  },
  {
    "path": "src/workspace/python/solutions/task15.py",
    "content": "def area(side):\n    print(side*side)\narea(20)\n"
  },
  {
    "path": "src/workspace/python/solutions/task16.py",
    "content": "def div(number = 3):\n    if(number%3 == 0):\n        print(\"Divisible\")\n    else:\n        print(\"Not Divisible\")\n\ndiv(16)\ndiv()\n"
  },
  {
    "path": "src/workspace/python/solutions/task17.py",
    "content": "def my_func(value):\n    return 17*value\na = my_func(14)\nprint(a)\n"
  },
  {
    "path": "src/workspace/python/solutions/task18.py",
    "content": "import time\n\nlocaltime = time.asctime(time.localtime(time.time()) )\nprint(localtime)\n"
  },
  {
    "path": "src/workspace/python/solutions/task19.py",
    "content": "import math\ndef square_root(value):\n    return math.sqrt(value)\na = square_root(3364)\nprint(a) \n"
  },
  {
    "path": "src/workspace/python/solutions/task2.py",
    "content": "print('variable')\nprint('product_of_12')\n"
  },
  {
    "path": "src/workspace/python/solutions/task20.py",
    "content": "random_list = [1,2,3,4,5,6,7,8,9,10]\nfor i in random_list:\n    if i%2==0:\n        print(i)\n    else:\n        continue\n"
  },
  {
    "path": "src/workspace/python/solutions/task21.py",
    "content": "list = [1,2,3,4,5,6,7,8,9,10]\n[ print(i) for i in list if i%2!=0 ]\n"
  },
  {
    "path": "src/workspace/python/solutions/task22.py",
    "content": "random_list = ['one', 'two', 'three']\ndef display(random_list):\n    for i in random_list:\n        print(i)\n\nif 'one' in random_list:\n    print('Found!')\nelse:\n    print('Not Found!')\nprint(len(random_list))\nrandom_list.append('four')\ndisplay(random_list)\nrandom_list.insert(1, 'five')\ndisplay(random_list)\nrandom_list.remove('one')\ndisplay(random_list)\nrandom_list.pop(0)\ndisplay(random_list)\ndel random_list[1]\ndisplay(random_list)\nrandom_list.clear()\nprint('Empty!')\n"
  },
  {
    "path": "src/workspace/python/solutions/task23.py",
    "content": "random_tuple = (100,200,300)\nfor i in random_tuple:\n    print(i)\nif 200 in random_tuple:\n    print('Found!')\nelse:\n    print('Not Found!')\nprint(len(random_tuple))\n"
  },
  {
    "path": "src/workspace/python/solutions/task24.py",
    "content": "dict_random = {1:'one', 2: 'two', 3: 'three'}\nfor i in dict_random:\n    print(i)\nfor i in dict_random:\n    print(dict_random[i])\nfor i,j in dict_random.items():\n    print(i,j)\nprint(len(dict_random))\ndict_random[4] = 'four'\nfor i,j in dict_random.items():\n    print(i,j)\n"
  },
  {
    "path": "src/workspace/python/solutions/task25.py",
    "content": "try:\n    print(1/0)\nexcept:\n    print('Zero Division not possible')\n"
  },
  {
    "path": "src/workspace/python/solutions/task26.py",
    "content": "def factorial(n):\n    if n == 1:\n        return 1\n    else:\n        return n*factorial(n-1)\na = factorial(6)\nprint(a)\n"
  },
  {
    "path": "src/workspace/python/solutions/task27.py",
    "content": "for i in range(1,5):\n    for j in range(1,i+1):\n        print('*', end='')\n    print('\\n')\n"
  },
  {
    "path": "src/workspace/python/solutions/task28.py",
    "content": "for i in range(1,11):\n    print(5*i)\n"
  },
  {
    "path": "src/workspace/python/solutions/task29.py",
    "content": "a = 103\nk = 0\nfor i in range(2,a//2+1):\n    if(a%i==0):\n        k=k+1\nif(k<=0):\n    print(\"Prime!\")\nelse:\n    print(\"Not Prime!\")\n"
  },
  {
    "path": "src/workspace/python/solutions/task3.py",
    "content": "str = 'hello world'\nprint(str.upper())\nprint(len(str))\n"
  },
  {
    "path": "src/workspace/python/solutions/task30.py",
    "content": "string = 'civic'\nif(string==string[::-1]):\n      print(\"Palindrome!\")\nelse:\n      print(\"Not Palindrome!\")\n"
  },
  {
    "path": "src/workspace/python/solutions/task4.py",
    "content": "a = 35\nb = 30\nc = 20\nsum = a+b+c\navg = sum/3\nprint(sum)\nprint(avg)"
  },
  {
    "path": "src/workspace/python/solutions/task5.py",
    "content": "a = 20\nif a%2==0:\n\tprint(\"Even\")\nelse:\n\tprint(\"Odd\")"
  },
  {
    "path": "src/workspace/python/solutions/task6.py",
    "content": "for i in range(1,11):\n\tif i%2 == 0:\n\t\tprint(i)"
  },
  {
    "path": "src/workspace/python/solutions/task7.py",
    "content": "i = 1\nwhile i<=10:\n\tprint(i*i)\n\ti = i+1\n"
  },
  {
    "path": "src/workspace/python/solutions/task8.py",
    "content": "for i in range(10,20):\n\tif(i == 15):\n\t\tcontinue\n\tif(i == 18):\n\t\tbreak\n\tprint(i)"
  },
  {
    "path": "src/workspace/python/solutions/task9.py",
    "content": "a = 90\nb = 85\nc = 70\nd = 75\ne = 80\navg = ((a+b+c+d+e)/5)\nprint(avg)\nif avg>90 and avg<100:\n    print('A+')\nelif avg>80 and avg<=90:\n    print('A')\nelif avg>70 and avg<=80:\n    print('B')\nelif avg>60 and avg<=70:\n    print('C')\nelif avg>50 and avg<=60:\n    print('D')\nelse:\n    print('F')\n"
  },
  {
    "path": "src/workspace/python/tasks.json",
    "content": "[\n  {\n    \"task\": \"Hey there folks, welcome to the world of programming\\n Task 1:-\\n Print Hello World to the console using the pre-built print function\"\n  },\n  {\n    \"task\": \"\\n Now lets focus on variables\\n Unlike other programming languages, Python has no command for declaring a variable.A variable is created the moment you first assign a value to it.\\n Also consider these variable naming conventions\\n\\n 1.A variable name must start with a letter or the underscore character\\n 2.A variable name cannot start with a number\\n 3.A variable name can only contain alpha-numeric characters and underscores (A-z, 0-9, and _ )\\n 3.Variable names are case-sensitive (age, Age and AGE are three different variables)\\n Task 2:-\\n Consider these variable names:-\\n variable\\n sum@\\n product_of_12\\n 12_product\\n Just print out the correct variable names in order\"\n  },\n  {\n    \"task\": \"\\nKeep it up!\\nStrings represent a group of characters. String literals in python are surrounded by either single quotation marks, or double quotation marks.Python provides various prebuilt functions to deal with strings, say to find the length of a string, convert it to lower case etc.\\nTask-3\\nDeclare a variable str and initialize it with hello world Print it in upper case and also the length in order\"\n  },\n  {\n    \"task\": \"\\nGreat work! Let's move on .... \\n Operators are used to perform operations on variables and values. \\n There are many types of operators: \\n 1. Arithmetic Operator \\n 2. Assignment Operator \\n 3. Comparison Operator \\n 4. Logical Operator \\n 5. Bitwise Operator \\n Enough talk, let's do the task. \\n\\n Task 4 \\n Initialize three variables a, b,c with values 35, 30, 20 respectively. \\n Your task is to print the sum and average of these three numbers.\"\n  },\n  {\n    \"task\": \"\\n Impressive! On to the next task ... \\n Conditional Statements are statements that execute when the given condition is TRUE. \\n Conditional statements are implemented using if-else statements. Here's your task: \\n\\n Task 5 \\n Store value 20 to the variable 'a', then print 'Odd' if it is odd. Else, print 'Even' if it is an even number.\"\n  },\n  {\n    \"task\": \"\\n Awesome! Let's move on to Loops. \\n Loop is an important statement which is used for repetition of the same code as and when required. \\n This task will surely test what you have learnt till now from the previous tasks! \\n\\n Task 6 \\n Syntax of for loop: \\n  for loop_control_variable in range(start, stop, step): \\n \\t Loop Body(indented)\\n Here's your task:  \\n\\n Task- 6 \\n Print even numbers from 1 to 10 (including 10) using for loop.\"\n  },\n  {\n    \"task\": \"\\n Let's move on to while loop now. This loop works similiar to that of a for loop. \\n Syntax of while loop: \\n while condition:\\n\\tLoop Body(Indented statements). \\n\\n Task 7 \\n Your task is to print the squares of the numbers from 1 to 10. Use while loop to do the task.\"\n  },\n  {\n    \"task\": \"\\n Great work! Let's move on to break and continue statements. \\n Break statements are used to break out of the loop when required and continue statements are used to skip the current iteration according to the condition given. \\n\\n Task 8: \\n Print the values from 10 to 20 but skip the value 15 and stop the iteration at value 18. \"\n  },\n  {\n    \"task\": \"\\n Let's move on to Logical Operators. Logical Operators are 'and', 'or', 'not'. \\n And operator returns true if both the conditions(operands) are true. \\n Or operator returns true if any one of the conditions is True. \\n Not operator negates the boolean value returned by the expression \\n\\n Task 9 \\n Rahul scores 90, 85,70, 75, 80 in his exams. The grading criteria for an exam is given below(based on average): \\n A+ => 91 -100 \\n A => 81-90 \\n B => 71-80 \\n C => 61- 70 \\n D => 51- 60 \\n F => 50 & Less than 50. \\n Calculate and print his average as well as the grade.\"\n  },\n  {\n    \"task\": \"\\n Awesome! Let's move on to Type Conversion in Python. \\n Type Conversion is used to directly convert one datatype to another which is useful in day-to day programming. \\n For example, you may want to find the average as an integer without that long trailing numbers after the decimal point. For this, we can use type conversion. \\n\\n Task 10 \\n Initialise three variables with the values 60,100,200 and find the average. Print the average as an integer.\"\n  },\n  {\n    \"task\": \"\\n Now let's move on to Type Coercion in Python. \\n Coercion happens in the case of binary operations: if you do x+y , and x and y have different types, \\n they are coerced into a single type before performing the operation. \\n\\n Task 11 \\n Initialize two numbers with values 10 and 12.506. Add them and print their sum and average. (This is the way how Python handles two datatypes by default).\"\n  },\n  {\n    \"task\": \"\\n Wonderful progress! Let's move on ... \\n Now that you have learnt strings, let's move on to some in-built functions for strings. \\n They are: \\n 1.strip() - To remove any whitespace from beginning or the end \\n 2. len() - To find the length of the string \\n 3. lower() - Returns the string in lower case \\n 4. upper() - Returns the string in upper case \\n 5. replace() - To replace the value in the string with another value. \\n\\n Task 12 \\n Store a string, ' This is Cool!' \\n Your task is to \\n 1. Remove the white spaces at the beginning and the end and print it. \\n 2. Find the length of the string and print it. \\n 3. Print it in lower case. \\n 4. Print it in upper case \\n 5. Replace T with t and print it.\"\n  },\n  {\n    \"task\": \"\\n Great! Now, let's learn about String Slicing. \\n To slice a string means to split a string into a substring. \\n A string is a character array which has index starting from 0. \\n To print the string, you can either directly print it or use it to print a part of it. \\n Eg: \\n b='Hello' \\n print(b[1:4]) \\n This prints the characters from index 1 to 4 (4 not included). Here's your task: \\n\\n Task 13 \\n Print the substring 'day' in 'Friday'.\"\n  },\n  {\n    \"task\": \"\\n Let's deal with strings again. The last character of the string can be accessed at the index -1. Use this logic to do the following task. \\n Task 14 \\n Reverse the string 'AJCE' and print it using for loop.\"\n  },\n  {\n    \"task\": \"\\n Great. You have now mastered the basics of strings. \\n Let's move on to the next topic: Functions. \\n Functions are block of statements that execute a particular task. \\n Functions are very useful in programs to shorten the length of the program, by not writing the same thing over and over again. \\n You can pass values to a function, which are known as arguments. \\n Syntax: \\n def func_name(arguments): \\n\\tFunction Body \\n The function body executes only when it is called, like this, func_name(arguments) \\n Now, here's your task:\\n\\n Task 15\\n Define a function that calculates area of a square. Pass the value side which is initialized to 20 and print the area by using the function.\"\n  },\n  {\n    \"task\": \"\\n Awesome! Let's move on to the next topic: Default Parameters. \\n The default parameters are used when you don't pass any values to the function. \\n Eg: \\n def func_name(default value=0): \\n\\tFunction Body \\n When no value is passed, the default value of the argument is 0. Here's your task: \\n\\n Task 16 \\n Define a function to check whether a number is divisible by 3 or not. Set the default value to 3.\\n Pass the value 16 to the function and in the next statement, call the function without any argument. \\n Print 'Divisible' if divisible by 3 else print 'Not Divisible'\"\n  },\n  {\n    \"task\": \"\\n Let's move on to return values. \\n Return values are values that are returned after the function performs the required function. \\n Syntax: return(value) \\n Here's your next task: \\n\\n Task 17 \\n Write a function that returns the (17*Value) and print the return value of the function. Pass the value 14 to the function and store the return value into a variable 'a' \\n Print the value of 'a'\"\n  },\n  {\n    \"task\": \"\\n Awesome! You have mastered the basics of Functions. Let's move on to the next topic: Modules. \\n A Module is a file consisting of Python code. A module can define functions, classes and variables. A module can also include runnable code.\\n Most commonly used modules are: math, time, os. \\n In order to use their functions, we can import them like: import module_name and use the functions defined inside the module by modulename.func_name(). Here's your task: \\n\\n Task 18 \\n Use the time module to print the current local time of your desktop. \\n Output Example: Thu Nov  1 18:42:18 2018\"\n  },\n  {\n    \"task\": \"\\n Impressive! Let's learn about the module math. \\n 'math' module gives access to mathematical functions used to calculate cos, sin values, min, max, exp. \\n Here's your task: \\n\\n Task 19 \\n Write a program to define a function which returns the square root of the value passed to it. Return the square root and print it. Import math module and use sqrt(). \\n Pass the value 3364.\"\n  },\n  {\n    \"task\": \"\\n Great work! You have reached the 20th Task!! \\n You have mastered the basics of modules. \\n Now let's move on to the next topic: Collection Data Types. \\n There are 4 collection datatypes. Let's begin with Lists. \\n A list is a collection which is ordered and which can be changed. \\n List elements are enclosed with Square Brackets []. Eg: randomlist = ['one','two'] \\n List stores the values in an order. It start with an index 0. \\n To access the first element in the list, you have to use list[0]. The first element is always stored in the index 0. \\n For traversing through a list, you can use a for loop. Eg: for i in list_name: \\n\\tprint(i) \\n Here's your task: \\n\\n Task 20 \\n Create a list with elements 1 to 10 and traverse through the list and print the even numbers.\"\n  },\n  {\n    \"task\": \"\\nWow! That's impressive! \\n Let's learn List Comprehensions. \\n List comprehensions provide a concise way to create lists. \\n It consists of brackets containing an expression followed by a for clause, then zero or more for or if clauses.\\n The result will be a new list resulting from evaluating the expression in the context of the for and if clauses which follow it. \\n Syntax: [ expression for item in list if conditional ] \\n This is equivalent to what you did in the previous task. \\n\\n Task 21 \\n Store numbers 1 to 10 in a list and print the odd numbers using List Comprehensions.\"\n  },\n  {\n    \"task\": \"\\n Let's deal with lists some more. There are many operations that can be performed on Lists. \\n They are: \\n 1. Checking whether the element exists in the list using 'in' keyword. \\n 2. To determine length of the list using len() \\n 3. To add items using append() \\n 4. To insert at specific index using insert() \\n 5. To remove a particular element using remove(element) \\n 6. Pop() - Removes at specified index or by default, the last one. \\n 7. del keyword removes the specified index. \\n 8.  clear() - Empties the whole list. \\n Here's your task.(Quite a hectic task!) \\n\\n Task 22 \\n Create a list with the values 'one', 'two', 'three'. Your task is to do the following: \\n 1. Search for the element one and print 'Found!' if found, else print 'Not Found!' \\n 2. Print the length of the list \\n 3. Add 'four' to the list using append() \\n 4. Insert 'five' at index 1 using insert() \\n 5. Remove 'one' from the list using remove() \\n 6. Remove the value at index 0 using pop() \\n 7. Delete the second element of the list using del \\n 8. Empty the remaining list and print 'Empty!' \\n Use a function display() to display the list after each and every operation.\"\n  },\n  {\n    \"task\": \"\\n Awesome! Now you have mastered the basics of Lists. \\n Let's go to the next one: Tuples. \\n A tuple is a collection which is ordered and unchangeable. In Python tuples are written with round brackets (). The only difference between List and Tuple is that you cannot modify the values of the list once created. \\n That means you cannot add or remove elements to the tuple. \\n This makes your next task easier :) \\n\\n Task 23 \\n Create a tuple with values 100,200,300 and perform the following operations: \\n 1. Print each value of the tuple using for loop. \\n 2. Check if '200' exists in the tuple using in keyword and print 'Found!' else print 'Not Found!'. \\n 3. Print the length of the tuple.\"\n  },\n  {\n    \"task\": \"\\n Now let's move on to the next one: Dictionaries. \\nA dictionary is a collection which is unordered, changeable and indexed. In Python dictionaries are written with curly brackets{}, and they have keys and values. \\n  Syntax: {key:value, key2:value2}\\n Unlike Tuples, you can modify the values here, like this, dictionary_name['key']= new_value \\n To print only the keys, \\n for i in dictionary_name: \\n\\tprint(i) \\n To print only the values, \\n for i in dict_name: \\n\\tprint(dict_name[i]) \\n To print both key and value, \\n for i,j in dict_name.items(): \\n\\tprint(i,j) \\n Here's your task: \\n\\n Task 24 \\n Initialize a dictionary with the key:values : 1:'one', 2:'two', 3: 'three' Your task is to print the elements of the dictionary(1. Keys only, 2. Values only, 3. Both key and values together) and print the length of the dictionary. Also, add the key:value pair, 4:'four' directly by assigning them to the dictionary, and print the updated dictionary(keys and values)\"\n  },\n  {\n    \"task\": \"\\n We have come to the last section of Python basics. \\n Congrats on reaching the 25th Task! \\n Next topic is Exception Handling \\n When an error occurs, or exception as we call it, Python will normally stop and generate an error message. These exceptions can be handled using the try statement. \\n Eg: try: \\n\\tprint(i) \\n except: \\n\\tprint('An Exception Occured') \\n When the try block raises an error, the except block statement gets executed. Without this try-except block, the program may crash. \\n Here's your task: \\n\\n Task 25 \\n Try printing the value of 1/0 and print 'Zero Division not possible' in the except block.\"\n  },\n  {\n    \"task\": \"\\n Congrats on Completing the tasks. Hope you are having a great go. Here are some bonus tasks. \\n\\n Task 26 \\n Factorial Program. Print the factorial of 6 using whatever you have learnt from the previous tasks. \\n Do not use the in-built functions.\"\n  },\n  {\n    \"task\": \"\\n Impressive! Let's go to the next one. \\n\\n Task 27 \\n Pattern Printing \\n Print the following pattern \\n * \\n ** \\n *** \\n ****\"\n  },\n  {\n    \"task\": \"\\n Now let's move on to the next one. \\n\\n Task 28 \\n Multiplication Table \\n Print the multiples of 5 in order from 1 to 10.\"\n  },\n  {\n    \"task\": \"\\n You are one task away from completing this... Great to see you progress... \\n Next task: \\n\\n Task 29 \\n Prime Number \\n Check whether 103 is prime or not and print 'Prime!' if prime else print 'Not Prime!'\"\n  },\n  {\n    \"task\": \"\\n Congrats!! You have reached the last task!!! \\n Next task: \\n\\n Task 30 (the last one! :) ) \\n\\n Task 30 \\n Palindrome \\n Check whether a string 'civic' is palindrome or not. Print 'Palindrome!' if yes, else print 'Not Palindrome!'\"\n  }\n]\n"
  }
]