Allergies

This commit is contained in:
2025-04-18 21:39:46 +02:00
parent 96bd169f8b
commit b7199d2a17
21 changed files with 33484 additions and 1 deletions
Generated Executable
+7522
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,5 +1,5 @@
module.exports = {
printWidth: 800,
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: false,
@@ -0,0 +1,31 @@
{
"authors": [
"CRivasGomez"
],
"contributors": [
"masters3d",
"SleeplessByte"
],
"files": {
"solution": [
"allergies.ts"
],
"test": [
"allergies.test.ts"
],
"example": [
".meta/proof.ci.ts"
]
},
"blurb": "Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.",
"custom": {
"version.tests.compatibility": "jest-29",
"flag.tests.task-per-describe": false,
"flag.tests.may-run-long": false,
"flag.tests.includes-optional": false,
"flag.tests.jest": true,
"flag.tests.tstyche": false
},
"source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.",
"source_url": "https://turing.edu"
}
@@ -0,0 +1 @@
{"track":"typescript","exercise":"allergies","id":"80d100683eac450eb62499c4eb734797","url":"https://exercism.org/tracks/typescript/exercises/allergies","handle":"briemens","is_requester":true,"auto_approve":false}
Generated Executable
+16683
View File
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
{
"recommendations": [
"arcanis.vscode-zipfs",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
+7
View File
@@ -0,0 +1,7 @@
{
"cSpell.words": ["exercism"],
"search.exclude": {
"**/.yarn": true,
"**/.pnp.*": true
}
}
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
compressionLevel: mixed
enableGlobalCache: true
+50
View File
@@ -0,0 +1,50 @@
# Help
## Running the tests
Before trying to execute the tests, ensure the assignment folder is set-up correctly by following the installation steps, namely `corepack yarn install` and the Editor SDK setup.
Execute the tests with:
```bash
$ corepack yarn test
```
## Skipped tests
In the test suites all tests but the first have been skipped.
Once you get a test passing, you can enable the next one by changing `xit` to `it`.
Additionally tests may be grouped using `xdescribe`.
Enable the group by changing that to `describe`.
Finally, some exercises may have optional tests `it.skip`.
Remove `.skip` to execute the optional test.
## Submitting your solution
You can submit your solution using the `exercism submit allergies.ts` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [TypeScript track's documentation](https://exercism.org/docs/tracks/typescript)
- The [TypeScript track's programming category on the forum](https://forum.exercism.org/c/programming/typescript)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [TypeScript QuickStart](https://www.typescriptlang.org/docs/handbook/release-notes/overview.html)
- [ECMAScript 2015 Language Specification](https://www.ecma-international.org/wp-content/uploads/ECMA-262_6th_edition_june_2015.pdf) (pdf)
- [Mozilla JavaScript Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference)
- [/r/typescript](https://www.reddit.com/r/typescript) is the TypeScript subreddit.
- [StackOverflow](https://stackoverflow.com/questions/tagged/typescript) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.
+47
View File
@@ -0,0 +1,47 @@
# Allergies
Welcome to Allergies on Exercism's TypeScript Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.
An allergy test produces a single numeric score which contains the information about all the allergies the person has (that they were tested for).
The list of items (and their value) that were tested are:
- eggs (1)
- peanuts (2)
- shellfish (4)
- strawberries (8)
- tomatoes (16)
- chocolate (32)
- pollen (64)
- cats (128)
So if Tom is allergic to peanuts and chocolate, he gets a score of 34.
Now, given just that score of 34, your program should be able to say:
- Whether Tom is allergic to any one of those allergens listed above.
- All the allergens Tom is allergic to.
Note: a given score may include allergens **not** listed above (i.e. allergens that score 256, 512, 1024, etc.).
Your program should ignore those components of the score.
For example, if the allergy score is 257, your program should only report the eggs (1) allergy.
## Source
### Created by
- @CRivasGomez
### Contributed to by
- @masters3d
- @SleeplessByte
### Based on
Exercise by the JumpstartLab team for students at The Turing School of Software and Design. - https://turing.edu
+115
View File
@@ -0,0 +1,115 @@
import { describe, it, expect } from '@jest/globals'
import { Allergies } from './allergies.ts'
describe('allergicTo', () => {
it('no allergies means not allergic', () => {
const allergies = new Allergies(0)
expect(allergies.allergicTo('peanuts')).toBeFalsy()
expect(allergies.allergicTo('cats')).toBeFalsy()
expect(allergies.allergicTo('strawberries')).toBeFalsy()
})
it('is allergic to eggs', () => {
const allergies = new Allergies(1)
expect(allergies.allergicTo('eggs')).toBeTruthy()
})
it('allergic to eggs in addition to other stuff', () => {
const allergies = new Allergies(5)
expect(allergies.allergicTo('eggs')).toBeTruthy()
expect(allergies.allergicTo('shellfish')).toBeTruthy()
expect(allergies.allergicTo('strawberries')).toBeFalsy()
})
})
describe('list', () => {
it('no allergies at all', () => {
const allergies = new Allergies(0)
const expected: string[] = []
expect(allergies.list()).toEqual(expected)
})
it('allergic to just eggs', () => {
const allergies = new Allergies(1)
const expected = ['eggs']
expect(allergies.list()).toEqual(expected)
})
it('allergic to just peanuts', () => {
const allergies = new Allergies(2)
const expected = ['peanuts']
expect(allergies.list()).toEqual(expected)
})
it('allergic to just strawberries', () => {
const allergies = new Allergies(8)
const expected = ['strawberries']
expect(allergies.list()).toEqual(expected)
})
it('allergic to eggs and peanuts', () => {
const allergies = new Allergies(3)
const expected = ['eggs', 'peanuts']
expect(allergies.list()).toEqual(expected)
})
it('allergic to more than eggs but not peanuts', () => {
const allergies = new Allergies(5)
const expected = ['eggs', 'shellfish']
expect(allergies.list()).toEqual(expected)
})
it('allergic to lots of stuff', () => {
const allergies = new Allergies(248)
const expected = ['strawberries', 'tomatoes', 'chocolate', 'pollen', 'cats']
expect(allergies.list()).toEqual(expected)
})
it('allergic to everything', () => {
const allergies = new Allergies(255)
const expected = [
'eggs',
'peanuts',
'shellfish',
'strawberries',
'tomatoes',
'chocolate',
'pollen',
'cats',
]
expect(allergies.list()).toEqual(expected)
})
it('ignore non allergen score parts', () => {
const allergies = new Allergies(509)
const expected = [
'eggs',
'shellfish',
'strawberries',
'tomatoes',
'chocolate',
'pollen',
'cats',
]
expect(allergies.list()).toEqual(expected)
})
it('ignore non allergen score parts, without highest valid score', () => {
const allergies = new Allergies(257)
const expected = ['eggs']
expect(allergies.list()).toEqual(expected)
})
})
+26
View File
@@ -0,0 +1,26 @@
const allergenMap = {
eggs: 1,
peanuts: 2,
shellfish: 4,
strawberries: 8,
tomatoes: 16,
chocolate: 32,
pollen: 64,
cats: 128,
} as const
type Allergen = keyof typeof allergenMap
export class Allergies {
constructor(private _allergenIndex: number) {}
public list(): Allergen[] {
return Object.entries(allergenMap)
.filter(([_, weight]) => (this._allergenIndex & weight) !== 0)
.map(([allergen]) => allergen as Allergen)
}
public allergicTo(allergen: Allergen): boolean {
return this.list().includes(allergen)
}
}
+5
View File
@@ -0,0 +1,5 @@
module.exports = {
// eslint-disable-next-line @typescript-eslint/no-require-imports
presets: [[require('@exercism/babel-preset-typescript'), { corejs: '3.38' }]],
plugins: [],
}
+26
View File
@@ -0,0 +1,26 @@
// @ts-check
import tsEslint from 'typescript-eslint'
import config from '@exercism/eslint-config-typescript'
import maintainersConfig from '@exercism/eslint-config-typescript/maintainers.mjs'
export default [
...tsEslint.config(...config, {
files: ['.meta/proof.ci.ts', '.meta/exemplar.ts', '*.test.ts'],
extends: maintainersConfig,
}),
{
ignores: [
// # Protected or generated
'.git/**/*',
'.vscode/**/*',
//# When using npm
'node_modules/**/*',
// # Configuration files
'babel.config.cjs',
'jest.config.cjs',
],
},
]
+22
View File
@@ -0,0 +1,22 @@
module.exports = {
verbose: true,
projects: ['<rootDir>'],
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
'**/test/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[jt]s?(x)',
],
testPathIgnorePatterns: [
'/(?:production_)?node_modules/',
'.d.ts$',
'<rootDir>/test/fixtures',
'<rootDir>/test/helpers',
'__mocks__',
],
transform: {
'^.+\\.[jt]sx?$': 'babel-jest',
},
moduleNameMapper: {
'^(\\.\\/.+)\\.js$': '$1',
},
}
+38
View File
@@ -0,0 +1,38 @@
{
"name": "@exercism/typescript-allergies",
"version": "1.0.0",
"description": "Exercism exercises in Typescript.",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/exercism/typescript"
},
"type": "module",
"engines": {
"node": "^18.16.0 || >=20.0.0"
},
"devDependencies": {
"@exercism/babel-preset-typescript": "^0.6.0",
"@exercism/eslint-config-typescript": "^0.8.0",
"@jest/globals": "^29.7.0",
"@types/node": "~22.7.6",
"babel-jest": "^29.7.0",
"core-js": "~3.38.1",
"eslint": "^9.12.0",
"expect": "^29.7.0",
"jest": "^29.7.0",
"prettier": "^3.3.3",
"tstyche": "^2.1.1",
"typescript": "~5.6.3",
"typescript-eslint": "^8.10.0"
},
"scripts": {
"test": "corepack yarn node test-runner.mjs",
"test:types": "corepack yarn tstyche",
"test:implementation": "corepack yarn jest --no-cache --passWithNoTests",
"lint": "corepack yarn lint:types && corepack yarn lint:ci",
"lint:types": "corepack yarn tsc --noEmit -p .",
"lint:ci": "corepack yarn eslint . --ext .tsx,.ts"
},
"packageManager": "yarn@4.5.1"
}
+111
View File
@@ -0,0 +1,111 @@
#!/usr/bin/env node
/**
* 👋🏽 Hello there reader,
*
* It looks like you are working on this solution using the Exercism CLI and
* not the online editor. That's great! The file you are looking at executes
* the various steps the online test-runner also takes.
*
* @see https://github.com/exercism/typescript-test-runner
*
* TypeScript track exercises generally consist of at least two out of three
* types of tests to run.
*
* 1. tsc, the TypeScript compiler. This tests if the TypeScript code is valid
* 2. tstyche, static analysis tests to see if the types used are expected
* 3. jest, runtime implementation tests to see if the solution is correct
*
* If one of these three fails, this script terminates with -1, -2, or -3
* respectively. If it succeeds, it terminates with exit code 0.
*
* @note you need corepack (bundled with node LTS) enabled in order for this
* test runner to work as expected. Follow the installation and test
* instructions if you see errors about corepack or pnp.
*/
import { execSync } from 'node:child_process'
import { existsSync, readFileSync } from 'node:fs'
import { exit } from 'node:process'
import { URL } from 'node:url'
/**
* Before executing any tests, the test runner attempts to find the
* exercise config.json file which has metadata about which types of tests
* to run for this solution.
*/
const metaDirectory = new URL('./.meta/', import.meta.url)
const exercismDirectory = new URL('./.exercism/', import.meta.url)
const configDirectory = existsSync(metaDirectory)
? metaDirectory
: existsSync(exercismDirectory)
? exercismDirectory
: null
if (configDirectory === null) {
throw new Error(
'Expected .meta or .exercism directory to exist, but I cannot find it.'
)
}
const configFile = new URL('./config.json', configDirectory)
if (!existsSync(configFile)) {
throw new Error('Expected config.json to exist at ' + configFile.toString())
}
// Experimental: import config from './config.json' with { type: 'json' }
/** @type {import('./config.json') } */
const config = JSON.parse(readFileSync(configFile))
const jest = !config.custom || config.custom['flag.tests.jest']
const tstyche = config.custom?.['flag.tests.tstyche']
console.log(
`[tests] tsc: ✅, tstyche: ${tstyche ? '✅' : '❌'}, jest: ${jest ? '✅' : '❌'}, `
)
/**
* 1. tsc: the typescript compiler
*/
try {
console.log('[tests] tsc (compile)')
execSync('corepack yarn lint:types', {
stdio: 'inherit',
cwd: process.cwd(),
})
} catch {
exit(-1)
}
/**
* 2. tstyche: type tests
*/
if (tstyche) {
try {
console.log('[tests] tstyche (type tests)')
execSync('corepack yarn test:types', {
stdio: 'inherit',
cwd: process.cwd(),
})
} catch {
exit(-2)
}
}
/**
* 3. jest: implementation tests
*/
if (jest) {
try {
console.log('[tests] tstyche (implementation tests)')
execSync('corepack yarn test:implementation', {
stdio: 'inherit',
cwd: process.cwd(),
})
} catch {
exit(-3)
}
}
/**
* Done! 🥳
*/
+38
View File
@@ -0,0 +1,38 @@
{
"display": "Configuration for Exercism TypeScript Exercises",
"compilerOptions": {
// Allows you to use the newest syntax, and have access to console.log
// https://www.typescriptlang.org/tsconfig#lib
"lib": ["ES2020", "dom"],
// Make sure typescript is configured to output ESM
// https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#how-can-i-make-my-typescript-project-output-esm
"module": "Node16",
// Since this project is using babel, TypeScript may target something very
// high, and babel will make sure it runs on your local Node version.
// https://babeljs.io/docs/en/
"target": "ES2020", // ESLint doesn't support this yet: "es2022",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
// Because jest-resolve isn't like node resolve, the absolute path must be .ts
"allowImportingTsExtensions": true,
"noEmit": true,
// Because we'll be using babel: ensure that Babel can safely transpile
// files in the TypeScript project.
//
// https://babeljs.io/docs/en/babel-plugin-transform-typescript/#caveats
"isolatedModules": true
},
"include": [
"*.ts",
"*.tsx",
".meta/*.ts",
".meta/*.tsx",
"__typetests__/*.tst.ts"
],
"exclude": ["node_modules"]
}
File diff suppressed because it is too large Load Diff