diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 54aeff6dac747d8cc0a79cccdf2071f439a44d80..d973ee1854dc6f37789e28b60079c2a4a4640873 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -21,3 +21,4 @@ include:
   - local: "/puissance-4/.gitlab-ci.yml"
   - local: "/trip-service-kata-typescript/.gitlab-ci.yml"
   - local: "/roman-calculator/.gitlab-ci.yml"
+  - local: "/h2g2/.gitlab-ci.yml"
diff --git a/README.md b/README.md
index 8cd766f2a555ae960c8f4dc979ea9a28a612022b..fcfc29ee791ffa641894ae6a604502ede24a1274 100644
--- a/README.md
+++ b/README.md
@@ -45,3 +45,4 @@ Ce dépôt Git a pour but de partager les différents ateliers pouvant être ré
 | [Trip service (TypeScript)](/trip-service-kata-typescript)                                                            | Kata        | Moyenne    |
 | [Roman calculator](/roman-calculator)                                                                                 | Kata        | Moyenne    |
 | [Atomic Design I and II](https://gitlab.ippon.fr/arey/pattern-library)                                                | Front       | Moyenne    |
+| [H2G2 (TypeScript)](/h2g2)                                                                                            | Kata        | Moyenne    |
diff --git a/h2g2/.eslintrc.js b/h2g2/.eslintrc.js
new file mode 100644
index 0000000000000000000000000000000000000000..fd818a475e66b5f69bb8806570d63f8ca46ab19f
--- /dev/null
+++ b/h2g2/.eslintrc.js
@@ -0,0 +1,71 @@
+module.exports = {
+  root: true,
+  env: {
+    node: true,
+  },
+  extends: [
+    'eslint:recommended',
+    'plugin:@typescript-eslint/recommended',
+    'plugin:import/errors',
+    'plugin:import/warnings',
+    'plugin:import/typescript',
+  ],
+  plugins: ['prettier', '@typescript-eslint'],
+  rules: {
+    quotes: ['error', 'single', { avoidEscape: true }],
+    'comma-dangle': [
+      'error',
+      {
+        arrays: 'always-multiline',
+        objects: 'always-multiline',
+        imports: 'always-multiline',
+        exports: 'always-multiline',
+        functions: 'never',
+      },
+    ],
+    'import/order': [
+      'error',
+      {
+        alphabetize: {
+          order: 'asc',
+          caseInsensitive: true,
+        },
+        'newlines-between': 'always',
+      },
+    ],
+    'prettier/prettier': [
+      'error',
+      {
+        singleQuote: true,
+        trailingComma: 'es5',
+        printWidth: 140,
+      },
+    ],
+  },
+  settings: {
+    'import/resolver': {
+      typescript: {
+        alwaysTryTypes: true,
+      },
+    },
+    'import/core-modules': ['sinon'],
+  },
+  parserOptions: {
+    parser: '@typescript-eslint/parser',
+  },
+  overrides: [
+    {
+      files: ['**/__tests__/*.{j,t}s?(x)', '**/*.spec.{j,t}s?(x)'],
+      env: {
+        jest: true,
+      },
+    },
+    {
+      files: ['**/*.ts', '**/*.tsx'],
+      rules: {
+        'no-unused-vars': ['off'],
+        'no-undef': ['off'],
+      },
+    },
+  ],
+};
diff --git a/h2g2/.gitignore b/h2g2/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..291a1654e4fa05c2658e11d7b343d8ce7e562a0b
--- /dev/null
+++ b/h2g2/.gitignore
@@ -0,0 +1,3 @@
+/node_modules
+/.idea
+
diff --git a/h2g2/.gitlab-ci.yml b/h2g2/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..761b791f9a1192e8f12f3bf46d362a1f4d19663f
--- /dev/null
+++ b/h2g2/.gitlab-ci.yml
@@ -0,0 +1,11 @@
+h2g2:
+  variables:
+    PROJECT_FOLDER: "h2g2"
+  extends: .node14
+  only:
+    refs:
+      - master
+      - merge_requests
+    changes:
+      - ".gitlab-common-ci.yml"
+      - "h2g2/**/*"
diff --git a/h2g2/Potter.md b/h2g2/Potter.md
new file mode 100644
index 0000000000000000000000000000000000000000..73814f0dfff09485fb6ba3362e739681cf75024e
--- /dev/null
+++ b/h2g2/Potter.md
@@ -0,0 +1,106 @@
+# Potter
+
+If you want to try this Kata for yourself or at your dojo meeting, read
+the problem description and see if the Kata appeals to you. The rest is
+commentary and helpful clues for if you get stuck solving it. I would
+recommend trying the Kata for yourself before reading too much of it.
+
+## Problem Description
+
+Once upon a time there was a series of 5 books about a very English hero
+called Harry. (At least when this Kata was invented, there were only 5.
+Since then they have multiplied) Children all over the world thought he
+was fantastic, and, of course, so did the publisher. So in a gesture of
+immense generosity to mankind, (and to increase sales) they set up the
+following pricing model to take advantage of Harry's magical powers.
+
+One copy of any of the five books costs 8 EUR. If, however, you buy two
+different books from the series, you get a 5% discount on those two
+books. If you buy 3 different books, you get a 10% discount. With 4
+different books, you get a 20% discount. If you go the whole hog, and
+buy all 5, you get a huge 25% discount.
+
+Note that if you buy, say, four books, of which 3 are different titles,
+you get a 10% discount on the 3 that form part of a set, but the fourth
+book still costs 8 EUR.
+
+Potter mania is sweeping the country and parents of teenagers everywhere
+are queueing up with shopping baskets overflowing with Potter books.
+Your mission is to write a piece of code to calculate the price of any
+conceivable shopping basket, giving as big a discount as possible.
+
+For example, how much does this basket of books cost?
+
+* 2 copies of the first book
+* 2 copies of the second book
+* 2 copies of the third book
+* 1 copy of the fourth book
+* 1 copy of the fifth book
+
+answer : 
+    
+      (4 * 8) - 20% [first book, second book, third book, fourth book]
+    + (4 * 8) - 20% [first book, second book, third book, fifth book]
+    = 25.6 * 2
+    = 51.20
+       
+## Clues
+
+You’ll find that this Kata is easy at the start. You can get going with
+tests for baskets of 0 books, 1 book, 2 identical books, 2 different
+books… and it is not too difficult to work in small steps and gradually
+introduce complexity.
+
+However, the twist becomes apparent when you sit down and work out how
+much you think the sample basket above should cost. It isn’t
+`5 * 8 * 0.75 + 3 *8 * 0.90`. It is in fact `4 * 8 * 0.8 + 4 * 8 * 0.8`. So the trick
+with this Kata is not that the acceptance test you’ve been given is
+wrong. The trick is that you have to write some code that is intelligent
+enough to notice that two sets of four books is cheaper than a set of
+five and a set of three.
+
+You will have to introduce a certain amount of clever optimization
+algorithm. But not too much! This problem does not require a fully
+fledged general purpose optimizer. Try to solve just this problem well
+in order to share it for everyone or even in the ??? . Trust that you
+can generalize and improve your solution if and when new requirements
+come along.
+
+- This application has nice application for
+
+## Suggested Test Cases
+
+(Originally posted at xp-france)
+
+    def testBasics
+      assert_equal(0, price([]))
+      assert_equal(8, price([1]))
+      assert_equal(8, price([2]))
+      assert_equal(8, price([3]))
+      assert_equal(8, price([4]))
+      assert_equal(8 * 3, price([1, 1, 1]))
+    end
+
+    def testSimpleDiscounts
+      assert_equal(8 * 2 * 0.95, price([0, 1]))
+      assert_equal(8 * 3 * 0.9, price([0, 2, 4]))
+      assert_equal(8 * 4 * 0.8, price([0, 1, 2, 4]))
+      assert_equal(8 * 5 * 0.75, price([0, 1, 2, 3, 4]))
+    end
+
+    def testSeveralDiscounts
+      assert_equal(8 + (8 * 2 * 0.95), price([0, 0, 1]))
+      assert_equal(2 * (8 * 2 * 0.95), price([0, 0, 1, 1]))
+      assert_equal((8 * 4 * 0.8) + (8 * 2 * 0.95), price([0, 0, 1, 2, 2, 3]))
+      assert_equal(8 + (8 * 5 * 0.75), price([0, 1, 1, 2, 3, 4]))
+    end
+
+    def testEdgeCases
+      assert_equal(2 * (8 * 4 * 0.8), price([0, 0, 1, 1, 2, 2, 3, 4]))
+      assert_equal(3 * (8 * 5 * 0.75) + 2 * (8 * 4 * 0.8), 
+        price([0, 0, 0, 0, 0, 
+               1, 1, 1, 1, 1, 
+               2, 2, 2, 2, 
+               3, 3, 3, 3, 3, 
+               4, 4, 4, 4]))
+    end
diff --git a/h2g2/README.md b/h2g2/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b7e90ca06053b059137225784c1e5586eaff1059
--- /dev/null
+++ b/h2g2/README.md
@@ -0,0 +1,9 @@
+# H2G2
+
+Kata Potter, mais on l'a renommé H2G2 parce que la série Harry Potter comporte 7 livres et non 5 alors que la trilogie en cinq volumes de Douglas Adams en comporte 5, en même temps c'est ce qui est écrit dans l'intitulé.
+
+-   **Auteurs** : Léa COSTON et Anthony REY
+-   **Date** : 06/10/2020
+-   **Langage** : TypeScript
+-   **Niveau** : Moyen
+-   **Replay** : [H2G2 Kata - Léa et Anthony](https://www.youtube.com/watch?v=XB2c8fj_Aus)
diff --git a/h2g2/jest.config.js b/h2g2/jest.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..c4fc7e4220dfb1bb7c0c1c72c0db0de400344234
--- /dev/null
+++ b/h2g2/jest.config.js
@@ -0,0 +1,9 @@
+module.exports = {
+  roots: ['<rootDir>/src'],
+  transform: {
+    '^.+\\.tsx?$': 'ts-jest',
+  },
+  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
+  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
+  testEnvironment: 'node',
+};
diff --git a/h2g2/package.json b/h2g2/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..2c2831633b19dc07dea41960cf36029114e4e914
--- /dev/null
+++ b/h2g2/package.json
@@ -0,0 +1,28 @@
+{
+  "name": "h2g2",
+  "version": "1.0.0",
+  "description": "Code retreat",
+  "main": "src/index.ts",
+  "dependencies": {
+    "@types/jest": "^26.0.15",
+    "@typescript-eslint/eslint-plugin": "^4.6.1",
+    "@typescript-eslint/parser": "^4.6.1",
+    "eslint": "^7.13.0",
+    "eslint-import-resolver-typescript": "^2.3.0",
+    "eslint-plugin-import": "^2.22.1",
+    "eslint-plugin-prettier": "^3.1.4",
+    "jest": "^26.6.3",
+    "prettier": "^2.1.2",
+    "ts-jest": "^26.4.3",
+    "typescript": "^4.0.5"
+  },
+  "scripts": {
+    "test": "jest",
+    "test:watch": "jest --watch",
+    "test:watch:all": "jest --watchAll",
+    "eslint:ci": "eslint './**/*.{ts,js}'",
+    "eslint": "eslint './**/*.{ts,js}' --fix"
+  },
+  "author": "Anthony REY",
+  "license": "MIT"
+}
diff --git a/h2g2/src/.gitkeep b/h2g2/src/.gitkeep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/h2g2/src/H2G2.spec.ts b/h2g2/src/H2G2.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1be092f9faf1d6b5cc47b5c6df69b0f72a21a5b3
--- /dev/null
+++ b/h2g2/src/H2G2.spec.ts
@@ -0,0 +1,121 @@
+const BOOK_PRICE = 8;
+const DISCOUNT_TWO_BOOKS = 0.95;
+const DISCOUNT_THREE_BOOKS = 0.9;
+const DISCOUNT_FOUR_BOOKS = 0.8;
+const DISCOUNT_FIVE_BOOKS = 0.75;
+
+const DISCOUNT = new Map([
+  [2, DISCOUNT_TWO_BOOKS],
+  [3, DISCOUNT_THREE_BOOKS],
+  [4, DISCOUNT_FOUR_BOOKS],
+  [5, DISCOUNT_FIVE_BOOKS],
+]);
+
+enum Book {
+  FIRST = 'FIRST',
+  SECOND = 'SECOND',
+  THIRD = 'THIRD',
+  FOURTH = 'FOURTH',
+  FIFTH = 'FIFTH',
+}
+
+const discountFor = (distinct: number): number => DISCOUNT.get(distinct) || 1;
+
+const maxSerie = (occurences: Map<Book, number>) =>
+  Array.from(occurences)
+    .map(([, number]) => number)
+    .filter((number) => number > 0).length;
+
+function decrementOccurence(occurence: number) {
+  if (occurence === 0) {
+    return 0;
+  }
+  return occurence - 1;
+}
+
+const decrementSerie = (occurences: Map<Book, number>): Map<Book, number> =>
+  new Map(Array.from(occurences).map(([book, occurence]) => [book, decrementOccurence(occurence)]));
+
+const getOccurences = (books: Book[]) =>
+  new Map(
+    [Book.FIRST, Book.SECOND, Book.THIRD, Book.FOURTH, Book.FIFTH].map((book) => [
+      book,
+      books.filter((currentBook) => currentBook === book).length,
+    ])
+  );
+
+const fill = (number: number, size: number): number[] => Array(number).fill(size);
+
+const optimizePacks = (packs: number[]): number[] => {
+  const one = packs.filter((size) => size === 1).length;
+  const two = packs.filter((size) => size === 2).length;
+  const three = packs.filter((size) => size === 3).length;
+  const four = packs.filter((size) => size === 4).length;
+  const five = packs.filter((size) => size === 5).length;
+
+  const difference = Math.min(three, five);
+  return [
+    ...fill(one, 1),
+    ...fill(two, 2),
+    ...fill(three - difference, 3),
+    ...fill(four + difference * 2, 4),
+    ...fill(five - difference, 5),
+  ];
+};
+
+const price = (books: Book[]): number => {
+  let occurences = getOccurences(books);
+
+  const packs: number[] = [];
+
+  while (maxSerie(occurences) > 0) {
+    packs.push(maxSerie(occurences));
+    occurences = decrementSerie(occurences);
+  }
+
+  return optimizePacks(packs)
+    .map((size) => size * BOOK_PRICE * discountFor(size))
+    .reduce((accumulation, current) => accumulation + current, 0);
+};
+
+describe('H2G2', () => {
+  it('Price of no book should be 0', () => {
+    expect(price([])).toBe(0);
+  });
+
+  it('Price of one book is 8', () => {
+    expect(price([Book.FIRST])).toBe(8);
+  });
+
+  it('Price of same book is 8 each', () => {
+    expect(price([Book.SECOND, Book.SECOND, Book.SECOND, Book.SECOND])).toBe(32);
+  });
+
+  it('Price two different books should have 5% off', () => {
+    expect(price([Book.THIRD, Book.FOURTH])).toBe(8 * 2 * 0.95);
+  });
+
+  it('Price three different books should have 10% off', () => {
+    expect(price([Book.THIRD, Book.FOURTH, Book.FIFTH])).toBe(8 * 3 * 0.9);
+  });
+
+  it('Price four different books should have 20% off', () => {
+    expect(price([Book.FIRST, Book.THIRD, Book.FOURTH, Book.FIFTH])).toBe(8 * 4 * 0.8);
+  });
+
+  it('Price five different books should have 25% off', () => {
+    expect(price([Book.FIRST, Book.SECOND, Book.THIRD, Book.FOURTH, Book.FIFTH])).toBe(8 * 5 * 0.75);
+  });
+
+  it('Should discount of two different series be independent', () => {
+    expect(price([Book.FIRST, Book.SECOND, Book.THIRD, Book.FOURTH, Book.FIFTH, Book.FIRST, Book.SECOND])).toBe(
+      8 * 5 * 0.75 + 8 * 2 * 0.95
+    );
+  });
+
+  it('Should treat price of edge case', () => {
+    expect(price([Book.FIRST, Book.SECOND, Book.THIRD, Book.FOURTH, Book.FIFTH, Book.FIRST, Book.SECOND, Book.FOURTH])).toBe(
+      8 * 4 * 2 * 0.8
+    );
+  });
+});
diff --git a/h2g2/tsconfig.json b/h2g2/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..67e3cb36387cd46f5592853091cbc7dc1ff11091
--- /dev/null
+++ b/h2g2/tsconfig.json
@@ -0,0 +1,18 @@
+{
+  "compilerOptions": {
+    "target": "ES2020",
+    "module": "commonjs",
+    "noImplicitAny": true,
+    "removeComments": true,
+    "preserveConstEnums": true,
+    "outFile": "dist/main.js",
+    "sourceMap": true
+  },
+  "include": [
+    "src/**/*"
+  ],
+  "exclude": [
+    "node_modules",
+    "**/*.spec.ts"
+  ]
+}