Index: backend/.gitignore
===================================================================
--- backend/.gitignore	(revision ce371e5a1f811d4ff62f84fbd74dbef9a2b668f3)
+++ backend/.gitignore	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
@@ -4,2 +4,4 @@
 
 /generated/prisma
+
+/scripts
Index: backend/challenges/Challenges.json
===================================================================
--- backend/challenges/Challenges.json	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
+++ backend/challenges/Challenges.json	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
@@ -0,0 +1,353 @@
+[
+  {
+    "title": "a-phone-code",
+    "description": "Your task is to calculate the length of the longest common starting sequence (prefix) among a list of phone numbers, which represents the city's phone code.",
+    "examples": [
+      {
+        "input": "3\n007\n00123\n00124",
+        "output": "2"
+      },
+      {
+        "input": "4\n12345\n123\n123987\n123456",
+        "output": "3"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "acronyms",
+    "description": "Develop a function that takes a sentence and converts it into its acronym by taking the first letter of each word.",
+    "examples": [
+      {
+        "input": "Programming Challenges is really cool",
+        "output": "PCIRC"
+      },
+      {
+        "input": "Portable Network Graphics",
+        "output": "PNG"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "caesar-cipher",
+    "description": "Implement a function that encrypts a message using the Caesar cipher technique, which involves shifting each letter of the alphabet by a specified number of places.",
+    "examples": [
+      {
+        "input": "'ANTHONY', -3",
+        "output": "XKQELKV"
+      },
+      {
+        "input": "'JULIUS CAESAR', 3",
+        "output": "MXOLXV FDHVDU"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "cakes-swerc-2020-2021",
+    "description": "You need to determine the maximum number of cakes you can bake given a list of required ingredients per cake and the quantities of those ingredients you currently possess.",
+    "examples": [
+      {
+        "input": "3\n100 500\n2 5\n70 1000",
+        "output": "2"
+      },
+      {
+        "input": "3\n100 50\n2 5\n70 1000",
+        "output": "0"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "camel-case",
+    "description": "Construct a function that converts a standard string into camelCase format, where all words except the first begin with a capital letter and are joined without spaces.",
+    "examples": [
+      {
+        "input": "hello world",
+        "output": "helloWorld"
+      },
+      {
+        "input": "first name",
+        "output": "firstName"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "consecutive-numbers",
+    "description": "Design a function that identifies and returns all sequences of consecutive integers within a given list of numbers. The required length for a sequence to be considered 'consecutive' is given as the first input.",
+    "examples": [
+      {
+        "input": "2\n5 ; 1 ; 2 ; 3 ; 8 ; -5 ; -4 ; 7",
+        "output": "1 ; 2\n2 ; 3\n-5 ; -4"
+      },
+      {
+        "input": "3\n5 ; 1 ; 2 ; 3 ; 8 ; -5 ; -4 ; 7",
+        "output": "1 ; 2 ; 3"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "convert-number-from-base-to-another",
+    "description": "Create a function capable of converting a given natural number from its initial base to a target base. The function should handle bases from 2 to 36, using digits 0-9 and then capital letters A-Z.",
+    "examples": [
+      {
+        "input": "15\n10\n16",
+        "output": "F"
+      },
+      {
+        "input": "100000000\n2\n16",
+        "output": "100"
+      }
+    ],
+    "difficulty": "Medium"
+  },
+  {
+    "title": "fibonacci",
+    "description": "Your goal is to build a function that generates an array containing a specified quantity of Fibonacci numbers. The Fibonacci sequence starts with 0 and 1, and each subsequent number is the sum of the two preceding ones.",
+    "examples": [
+      {
+        "input": "8",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13]"
+      },
+      {
+        "input": "14",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "find-closest-number",
+    "description": "Given a list of integers and a separate target integer, your function must find and return the integer from the list that is numerically closest to the target.",
+    "examples": [
+      {
+        "input": "given_number: 3\narray: [1, 2, 3, 4, 5, 6]",
+        "output": "3"
+      },
+      {
+        "input": "given_number: 0\narray: [7, -10, 13, 8, 4, -7, -12, -3, 3, -9, 6, -1, -6, 7]",
+        "output": "-1"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "find-outlier-number",
+    "description": "You're provided an array of integers that is composed almost entirely of either odd or even numbers, with the exception of one unique number. Your task is to write a function that identifies and returns this single outlier.",
+    "examples": [
+      {
+        "input": "[2, 4, 0, 100, 4, 11, 2602, 36]",
+        "output": "11"
+      },
+      {
+        "input": "[160, 3, 1719, 19, 11, 13, -21]",
+        "output": "160"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "first-non-repeating-character",
+    "description": "Write a function to find the first character in a string that does not appear again in that string. If every character is repeated, the function should return an empty string.",
+    "examples": [
+      {
+        "input": "'stress'",
+        "output": "'t'"
+      },
+      {
+        "input": "'aabbcc'",
+        "output": "''"
+      }
+    ],
+    "difficulty": "Easy"
+  },
+  {
+    "title": "fizzbuzz",
+    "description": "Write a program that print the numbers from 1 to `n` but:\n\n- if number is divisible by 3, print `Fizz`\n- if number is divisible by 5, print `Buzz`\n- if number is divisible by both 3 and 5, print `FizzBuzz`\n- otherwise print the number",
+    "example": {
+      "input": "5",
+      "output": "1\n2\nFizz\n4\nBuzz"
+    },
+    "difficulty": "Easy"
+  },
+  {
+    "title": "frequency-deviation",
+    "description": "Given a string consisting of lowercase English letters, we define the frequency deviation of a substring as the difference between the maximum and the minimum frequencies of the characters in that substring.\n\nA substring of a string is formed by any contiguous segment of the string. For example, given \"bbacccc\", the character appearing most frequently is 'c' with $4$ occurrences. The character that appears the fewest times is 'a' with $1$ occurrence. The frequency deviation of the entire string is $4 - 1 = 3$.\n\nGiven a string, $s$, representing the input string, find the maximum possible frequency deviation of any of its substrings.",
+    "example": {
+      "input": "bbacccc",
+      "output": "3"
+    },
+    "difficulty": "Hard"
+  },
+  {
+    "title": "heap-algorithm",
+    "description": "Write a program that generates all possible unique permutations of a string.\n\nThe order of the generated permutations is important, see the example below.",
+    "example": {
+      "input": "abc",
+      "output": "abc\nbac\ncab\nacb\nbca\ncba"
+    },
+    "difficulty": "Medium"
+  },
+  {
+    "title": "hello-world",
+    "description": "Your function should return Hello depending of the parameter.",
+    "example": null,
+    "difficulty": "Easy"
+  },
+  {
+    "title": "is-palindrome",
+    "description": "The function should return `true` if a given string (case insensitive) is a palindrome and `false` if it's not the case.",
+    "example": null,
+    "difficulty": "Easy"
+  },
+  {
+    "title": "is-prime-number",
+    "description": "The function should return `true` if a given number is a prime number and `false` otherwise.",
+    "example": null,
+    "difficulty": "Easy"
+  },
+  {
+    "title": "is-valid-array-subsequence",
+    "description": "Given two non-empty arrays of integers, write a function that determines whether the second array is a subsequence of the first one.",
+    "example": {
+      "input": "5 1 22 25 6 -1 8 10\n1 6 -1 10",
+      "output": "true"
+    },
+    "difficulty": "Easy"
+  },
+  {
+    "title": "left-pad",
+    "description": "Create a function that pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. The padding is applied from the start (left) of the current string.",
+    "example": {
+      "input": "foo\n12\n-",
+      "output": "---------foo"
+    },
+    "difficulty": "Easy"
+  },
+  {
+    "title": "look-and-say-sequence-conway",
+    "description": "Write a program that prints the next term of the **look-and-say sequence**.",
+    "example": {
+      "input": "11",
+      "output": "21"
+    },
+    "difficulty": "Medium"
+  },
+  {
+    "title": "maximum-subarray-sum",
+    "description": "Given an array of `n` integers, find the contiguous subarray with the largest sum.",
+    "example": {
+      "input": "8\n-1\n2\n4\n-3\n5\n2\n-5\n2",
+      "output": "10"
+    },
+    "difficulty": "Medium"
+  },
+  {
+    "title": "offset-arrays",
+    "description": "To settle the debate of 0-based vs 1-based indexing I have created a language where you must explicitly state the range of indices an array should have.\n\nFor example, given an array definition \"A[-1..1] = 1 2 3\", you would have:\n\n- A[-1] = 1\n- A[0] = 2\n- A[1] = 3\n\nYou are given a list of `n` array definitions and your job is to figure out what number is found in a given index `i` of an array `arr`. Note that the indexing operations may be nested (in the above example, A[A[-1]] would produce result 3).",
+    "example": {
+      "input": "3\nA[-1..1] = 1 2 3\nB[3..7] = 3 4 5 6 7\nC[-2..1] = 1 2 3 4\nA[0]",
+      "output": "2"
+    },
+    "difficulty": "Medium"
+  },
+  {
+    "title": "prefix-suffix",
+    "description": "Write a programs that takes 2 strings (\"words\") and prints if one is a prefix/suffix of the other.",
+    "example": {
+      "input": "AlgoPy\nPy",
+      "output": "false\ntrue"
+    },
+    "difficulty": "Easy"
+  },
+  {
+    "title": "prime-numbers-decomposition",
+    "description": "In mathematics, product decomposition of prime factors (also known as integer factorization into prime numbers) involves writing a strictly positive integer as a product of prime numbers.",
+    "example": {
+      "input": "32",
+      "output": "2 * 2 * 2 * 2 * 2"
+    },
+    "difficulty": "Medium"
+  },
+  {
+    "title": "print-pyramid",
+    "description": "Display a pyramid of stars (`*`) whose height is given and in the right order (`normal` or `reverse`).",
+    "example": null,
+    "difficulty": "Easy"
+  },
+  {
+    "title": "reverse-polish-notation",
+    "description": "Your job is to create a calculator which evaluates expressions in Reverse Polish notation (a mathematical notation in which operators follow their operands. It does not need any parentheses as long as each operator has a fixed number of operands).",
+    "example": null,
+    "difficulty": "Medium"
+  },
+  {
+    "title": "roman-numerals",
+    "description": "The objective of this challenge is to create a function that translates a number into Roman numerals or the other way around.",
+    "example": null,
+    "difficulty": "Medium"
+  },
+  {
+    "title": "rotate-2-dimensional-array-90-degrees",
+    "description": "Given a square/rectangle matrix representing an image and a direction of rotation (`clockwise` or `anticlockwise`), rotate the image by 90 degrees.",
+    "example": {
+      "input": "clockwise\n1 2 3\n4 5 6\n7 8 9",
+      "output": "7 4 1\n8 5 2\n9 6 3"
+    },
+    "difficulty": "Medium"
+  },
+  {
+    "title": "single-number",
+    "description": "Given a **non-empty** array of integers, every element appears twice except for one. Find that single one.\n\nYou must implement a solution with a linear runtime complexity and use only constant extra space.",
+    "example": {
+      "input": "4\n1\n2\n1\n2",
+      "output": "4"
+    },
+    "difficulty": "Easy"
+  },
+  {
+    "title": "slugify",
+    "description": "Write a function that generates a slug from a string.\n\nA Slug is the unique identifying part of a web address, typically at the end of the URL.\n\nThe rules for generating a slug are as follows (`kebab-case`):\n\n- Replace spaces with hyphens.\n- Remove all non-alphanumeric characters.",
+    "example": {
+      "input": "hello world",
+      "output": "hello-world"
+    },
+    "difficulty": "Easy"
+  },
+  {
+    "title": "sorting-algorithms",
+    "description": "Write a function that takes a list of integers and sort them in ascending order.",
+    "example": null,
+    "difficulty": "Easy"
+  },
+  {
+    "title": "sudoku",
+    "description": "Write a program that solves the Sudoku given in input.\n\nThe empty cells are represented by 0.",
+    "example": {
+      "input": "5 3 0 0 7 0 0 0 0\n6 0 0 1 9 5 0 0 0\n0 9 8 0 0 0 0 6 0\n8 0 0 0 6 0 0 0 3\n4 0 0 8 0 3 0 0 1\n7 0 0 0 2 0 0 0 6\n0 6 0 0 0 0 2 8 0\n0 0 0 4 1 9 0 0 5\n0 0 0 0 8 0 0 7 9",
+      "output": "5 3 4 6 7 8 9 1 2\n6 7 2 1 9 5 3 4 8\n1 9 8 3 4 2 5 6 7\n8 5 9 7 6 1 4 2 3\n4 2 6 8 5 3 7 9 1\n7 1 3 9 2 4 8 5 6\n9 6 1 5 3 7 2 8 4\n2 8 7 4 1 9 6 3 5\n3 4 5 2 8 6 1 7 9"
+    },
+    "difficulty": "Hard"
+  },
+  {
+    "title": "triangle-type",
+    "description": "Given the lengths of the 3 sides of a triangle, your function should return whether it is `equilateral`, `isosceles`, `scalene` or `impossible`.",
+    "example": {
+      "input": "- **Line 1 to 3:** The length of each side of the triangle",
+      "output": null
+    },
+    "difficulty": "Easy"
+  },
+  {
+    "title": "valid-parentheses",
+    "description": "Given a string containing just the characters `'('`, `')'`, `'{'`, `'}'`, `'['` and `']'`, determine if the input string is valid.",
+    "example": {
+      "input": "()",
+      "output": "true"
+    },
+    "difficulty": "Easy"
+  }
+]
Index: backend/challenges/challenges-output.txt
===================================================================
--- backend/challenges/challenges-output.txt	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
+++ backend/challenges/challenges-output.txt	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
@@ -0,0 +1,1572 @@
+PROGRAMMING CHALLENGES
+=====================
+
+Generated on: 2025-06-08T08:43:48.583Z
+
+
+=== a-phone-code ===
+# a-phone-code
+
+Created by [@theoludwig](https://github.com/theoludwig) on 13 May 2025.
+
+## Instructions
+
+Polycarpus has n friends in Tarasov city. Polycarpus knows phone numbers of all his friends: they are strings s1, s2, ..., sn. All these strings consist only of digits and have the same length.
+
+Once Polycarpus needed to figure out Tarasov city phone code. He assumed that the phone code of the city is the longest common prefix of all phone numbers of his friends. In other words, it is the longest string c which is a prefix (the beginning) of each si for all i. Help Polycarpus determine the length of the city phone code.
+
+### Input
+
+The first line of the input contains an integer n — the number of Polycarpus's friends. The following n lines contain strings — the phone numbers of Polycarpus's friends. It is guaranteed that all strings consist only of digits and have the same length from 1 to 20, inclusive. It is also guaranteed that all strings are different.
+
+### Output
+
+Print the number of digits in the city phone code.
+
+## Source
+
+[Codeforces - A. Phone Code](https://codeforces.com/problemset/problem/172/A)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== acronyms ===
+# acronyms
+
+Created by [@theoludwig](https://github.com/theoludwig) on 30 June 2021.
+
+## Instructions
+
+Convert a given sentence to its acronym.
+
+## Examples
+
+### Example 1
+
+### Input
+
+```txt
+Programming Challenges is really cool
+```
+
+### Output
+
+```txt
+PCIRC
+```
+
+#### Output
+
+See the `test` folder for examples of input/output.
+
+
+=== ascii-art ===
+# ascii-art
+
+Created by [@theoludwig](https://github.com/theoludwig) on 1 May 2022.
+
+## Instructions
+
+### Goal
+
+In stations and airports you often see this type of screen:
+
+![Led Display](./led_display.jpg)
+
+Have you ever asked yourself how it might be possible to simulate this display on a good old terminal? We have: with ASCII art!
+
+### Rules
+
+ASCII art allows you to represent forms by using characters. To be precise, in our case, these forms are words. For example, the word "MANHATTAN" could be displayed as follows in ASCII art:
+
+```txt
+# #  #  ### # #  #  ### ###  #  ###
+### # # # # # # # #  #   #  # # # #
+### ### # # ### ###  #   #  ### # #
+# # # # # # # # # #  #   #  # # # #
+# # # # # # # # # #  #   #  # # # #
+```
+
+​Your mission is to write a program that can display a line of text in ASCII art in a style you are given as input.
+
+### Input
+
+- **Line 1:** The width `W` of a letter represented in ASCII art. All letters are the same width.
+- **Line 2:** The height `H` of a letter represented in ASCII art. All letters are the same height.
+- **Line 3:** The line of text `T`, composed of `N` ASCII characters.
+- **Following lines:** the string of characters `ABCDEFGHIJKLMNOPQRSTUVWXYZ?` Represented in ASCII art.
+
+### Output
+
+The text `T` in ASCII art.
+
+The characters a to z are shown in ASCII art by their equivalent in upper case.
+
+The characters that are not in the intervals `[a-z]` or `[A-Z]` will be shown as a question mark in ASCII art.
+
+### Constraints
+
+- $$0 < W < 30$$
+- $$0 < H < 30$$
+- $$0 < N < 200$$
+
+## Source
+
+[CodinGame](https://www.codingame.com/training/easy/ascii-art)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== caesar-cipher ===
+# caesar-cipher
+
+Created by [@theoludwig](https://github.com/theoludwig) on 25 June 2021.
+
+## Instructions
+
+In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher, Caesar's code or Caesar shift, is one of the simplest and most widely known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. For example, with a left shift of -3, D would be replaced by A, E would become B, and so on. The method is named after Julius Caesar, who used it in his private correspondence.
+
+### Example of the alphabet with a shift of +3 (shift to the right)
+
+```text
+Alphabet original   : ABCDEFGHIJKLMNOPQRSTUVWXYZ
+Alphabet rotated +3 : DEFGHIJKLMNOPQRSTUVWXYZABC
+```
+
+Create a function that will return the sentence after shifting the alphabet.
+
+- If it is a **positive** number then we shift the alphabet to the **right**
+- If it is a **negative** number then we shift the alphabet to the **left**
+
+### Example of Inputs
+
+```py
+'ANTHONY' # a character string (all capital letters)
+'-2' # an integer, the shift in the alphabet
+```
+
+## Source
+
+[Wikipedia - Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== cakes-swerc-2020-2021 ===
+# cakes-swerc-2020-2021
+
+Created by [@theoludwig](https://github.com/theoludwig) on 23 April 2022.
+
+## Instructions
+
+This summer, you plan to organize a large party and invite many
+friends. They have a sweet tooth, so you plan to bake nice cakes for them.
+You know the recipe for a nice chocolate cake, and you want to cook as
+many of them as possible.
+
+Given the `N` ingredients needed to make a single cake and the
+ingredients that you have in your kitchen, how many cakes can you
+make?
+
+### Input
+
+- **Line 1:** Single integer `N` for the number of ingredients.
+- **`N` next lines:** One for each ingredient. Each of these lines contains two positive integers: the first one is the required quantity of this ingredient per cake, the second one is the quantity of this ingredient you have in your kitchen.
+
+### Output
+
+The output should contain a single integer: the maximum number of cakes you can make using the
+available ingredients.
+
+### Constraints
+
+- $$1 \leq N \leq 10$$
+- All ingredient quantities will be integers between 1 and 10 000.
+
+## Source
+
+[SWERC 2020-2021 - Problem E: Cake](https://swerc.eu/2020/problems/)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+3
+100 500
+2 5
+70 1000
+```
+
+#### Output
+
+```txt
+2
+```
+
+### Example 2
+
+#### Input
+
+```txt
+3
+100 50
+2 5
+70 1000
+```
+
+#### Output
+
+```txt
+0
+```
+
+
+=== camel-case ===
+# camel-case
+
+Created by [@theoludwig](https://github.com/theoludwig) on 5 July 2020.
+
+## Instructions
+
+Write a simple camelCase function for strings. All words (except the first) must have their first letter capitalized without spaces.
+
+**Note:** camelCase is the practice of writing phrases such that each word in the middle of the phrase begins with a capital letter, with no intervening spaces or punctuation.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== consecutive-numbers ===
+# consecutive-numbers
+
+Created by [@theoludwig](https://github.com/theoludwig) on 28 June 2021.
+
+## Instructions
+
+Write a function which takes a list of integers, and which returns the list of of successive consecutive integers that there may be in the list.
+
+First input, is the number of consecutive numbers needed to consider it as "consecutive", the second input is the list of integers.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+2
+5 ; 1 ; 2 ; 3 ; 8 ; -5 ; -4 ; 7
+```
+
+#### Output
+
+```txt
+1 ; 2
+2 ; 3
+-5 ; -4
+```
+
+### Example 2
+
+#### Input
+
+```txt
+3
+5 ; 1 ; 2 ; 3 ; 8 ; -5 ; -4 ; 7
+```
+
+#### Output
+
+```txt
+1 ; 2 ; 3
+```
+
+
+=== convert-number-from-base-to-another ===
+# convert-number-from-base-to-another
+
+Created by [@theoludwig](https://github.com/theoludwig) on 20 October 2021.
+
+## Instructions
+
+Convert a natural number (`number`) from a certain base (`base_from`) to another base (`base_target`).
+
+For bases up to and including 10, we use the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9.
+
+For bases between 11 and 36, we use the 10 digits then the letters (capitals). For example, for base 16, the symbols used are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. For base 36, we uses the symbols 0,1,2,3,4,5,6,7,8,9, A, B, C, D, E, F, G, H, I, J, K, L, M, N , O, P, Q, R, S, T, U, V, W, X, Y, Z.
+
+### Input
+
+- **Line 1:** The `number` to be converted (natural number)
+- **Line 2:** The base of the number `base_from`
+- **Line 3:** The base to convert to `base_target`
+
+### Output
+
+The converted number.
+
+## Examples
+
+### Example 1
+
+#### Input
+
+```txt
+15
+10
+16
+```
+
+#### Output
+
+```txt
+F
+```
+
+### Example 2
+
+#### Input
+
+```txt
+100000000
+2
+16
+```
+
+#### Output
+
+```txt
+100
+```
+
+See the `test` folder for examples of input/output.
+
+
+=== defibrillators ===
+# defibrillators
+
+Created by [@theoludwig](https://github.com/theoludwig) on 28 June 2021.
+
+## Instructions
+
+### Goal
+
+The city of Montpellier has equipped its streets with defibrillators to help save victims of cardiac arrests. The data corresponding to [the position of all defibrillators](http://data.montpellier3m.fr/dataset/d%C3%A9fibrillateurs-de-montpellier) is available online.
+
+Based on the data we provide in the tests, write a program that will allow users to find the defibrillator nearest to their location using their mobile phone.
+
+### Rules
+
+The input data you require for your program is provided in text format.
+This data is comprised of lines, each of which represents a defibrillator. Each defibrillator is represented by the following fields:
+
+- A number identifying the defibrillator
+- Name
+- Address
+- Contact Phone number
+- Longitude (degrees)
+- Latitude (degrees)
+
+These fields are separated by a semicolon (`;`).
+
+**Beware:** the decimal numbers use the comma (,) as decimal separator. Remember to turn the comma (,) into dot (.) if necessary in order to use the data in your program.
+
+### Distance
+
+The distance `d` between two points `A` and `B` will be calculated using the following formula:
+
+![Distance Formula](./distance-formula.png)
+
+**Note:** In this formula, the latitudes and longitudes are expressed in radians. 6371 corresponds to the radius of the earth in km.
+
+The program will display the name of the defibrillator located the closest to the user’s position. This position is given as input to the program.
+
+### Input
+
+- **Line 1:** User's longitude (in degrees)
+- **Line 2:** User's latitude (in degrees)
+- **Line 3:** The number `N` of defibrillators located in the streets of Montpellier
+- **`N` next lines:** a description of each defibrillator
+
+### Output
+
+The name of the defibrillator located the closest to the user’s position.
+
+### Constraints
+
+- $$0 < N < 10 000$$
+
+## Source
+
+[CodinGame](https://www.codingame.com/training/easy/defibrillators)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== fibonacci ===
+# fibonacci
+
+Created by [@theoludwig](https://github.com/theoludwig) on 5 July 2020.
+
+## Instructions
+
+The function should return an array of fibonacci numbers. The function takes a `number` as an argument to decide how many number of elements to produce.
+
+**Note:** The Fibonacci Sequence is the series of numbers: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... Each subsequent number is the sum of the previous two.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== find-closest-number ===
+# find-closest-number
+
+Created by [@theoludwig](https://github.com/theoludwig) on 1 May 2022.
+
+## Instructions
+
+Given an array of `n` integers, find the closest value to the given number (`given_number`).
+
+## Input
+
+- **Line 1:** An integer `given_number` for the number to find the closest value to
+- **Line 2:** An integer `n` for the length of the list of integers
+- **`n` next lines:** the integers
+
+## Output
+
+The closest value in the array to the given number.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+3
+6
+1
+2
+3
+4
+5
+6
+```
+
+#### Output
+
+```txt
+3
+```
+
+**Explanation:** The given number is `3` and `3` is in the array, so the closest value is `3`.
+
+### Example 2
+
+#### Input
+
+```txt
+0
+14
+7
+-10
+13
+8
+4
+-7
+-12
+-3
+3
+-9
+6
+-1
+-6
+7
+```
+
+#### Output
+
+```txt
+-1
+```
+
+
+=== find-outlier-number ===
+# find-outlier-number
+
+Created by [@theoludwig](https://github.com/theoludwig) on 5 July 2020.
+
+## Instructions
+
+You are given an array (which will have a length of at least 3, but could be very large) containing integers. The array is either entirely comprised of odd integers or entirely comprised of even integers except for a single integer `N`. Write a function that takes the array as an argument and returns this "outlier" `N`.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== first-non-repeating-character ===
+# first-non-repeating-character
+
+Created by [@theoludwig](https://github.com/theoludwig) on 15 November 2020.
+
+## Instructions
+
+Write a function that takes a string input, and returns the first character that is not repeated anywhere in the string.
+
+For example, if given the input `'stress'`, the function should return `'t'`, since the letter `'t'` only occurs once in the string, and occurs first in the string.
+
+If a string contains all repeating characters, it should return an empty string (`""`).
+
+## Source
+
+[First non-repeating character - Codewars](https://www.codewars.com/kata/52bc74d4ac05d0945d00054e/)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== fizzbuzz ===
+# fizzbuzz
+
+Created by [@theoludwig](https://github.com/theoludwig) on 30 June 2021.
+
+## Instructions
+
+Write a program that print the numbers from 1 to `n` but:
+
+- if number is divisible by 3, print `Fizz`
+- if number is divisible by 5, print `Buzz`
+- if number is divisible by both 3 and 5, print `FizzBuzz`
+- otherwise print the number
+
+## Examples
+
+### Example 1
+
+#### Input
+
+```txt
+5
+```
+
+#### Output
+
+```txt
+1
+2
+Fizz
+4
+Buzz
+```
+
+See the `test` folder for examples of input/output.
+
+
+=== frequency-deviation ===
+# frequency-deviation
+
+Created by [@theoludwig](https://github.com/theoludwig) on 16 September 2023.
+
+## Instructions
+
+Given a string consisting of lowercase English letters, we define the frequency deviation of a substring as the difference between the maximum and the minimum frequencies of the characters in that substring.
+
+A substring of a string is formed by any contiguous segment of the string. For example, given "bbacccc", the character appearing most frequently is 'c' with $4$ occurrences. The character that appears the fewest times is 'a' with $1$ occurrence. The frequency deviation of the entire string is $4 - 1 = 3$.
+
+Given a string, $s$, representing the input string, find the maximum possible frequency deviation of any of its substrings.
+
+### Constraints
+
+- $$1 \leq s.length \leq 10^4$$
+- $s$ consists of lowercase English letters.
+
+## Source
+
+- [LeetCode - Substring With Largest Variance](https://leetcode.com/problems/substring-with-largest-variance/)
+- [Twitter @CoderNolimit](https://twitter.com/CoderNolimit/status/1668147202173050881)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+bbacccc
+```
+
+#### Output
+
+```txt
+3
+```
+
+### Example 2
+
+#### Input
+
+```txt
+aabb
+```
+
+#### Output
+
+```txt
+1
+```
+
+### Example 3
+
+#### Input
+
+```txt
+aaaaa
+```
+
+#### Output
+
+```txt
+0
+```
+
+
+=== heap-algorithm ===
+# heap-algorithm
+
+Created by [@theoludwig](https://github.com/theoludwig) on 8 November 2021.
+
+## Instructions
+
+Write a program that generates all possible unique permutations of a string.
+
+The order of the generated permutations is important, see the example below.
+
+## Source
+
+[Heap's Algorithm - Wikipedia](https://en.wikipedia.org/wiki/Heap%27s_algorithm)
+
+## Examples
+
+### Example 1
+
+#### Input
+
+```txt
+abc
+```
+
+#### Output
+
+```txt
+abc
+bac
+cab
+acb
+bca
+cba
+```
+
+See the `test` folder for examples of input/output.
+
+
+=== hello-world ===
+# hello-world
+
+Created by [@theoludwig](https://github.com/theoludwig) on 6 June 2021.
+
+## Instructions
+
+Your function should return Hello depending of the parameter.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== is-palindrome ===
+# is-palindrome
+
+Created by [@theoludwig](https://github.com/theoludwig) on 5 July 2020.
+
+## Instructions
+
+The function should return `true` if a given string (case insensitive) is a palindrome and `false` if it's not the case.
+
+**Note:** a **Palindrome** is a word, phrase, or sequence that reads the **same backwards as forwards**, e.g. Kayak.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== is-prime-number ===
+# is-prime-number
+
+Created by [@theoludwig](https://github.com/theoludwig) on 5 July 2020.
+
+## Instructions
+
+The function should return `true` if a given number is a prime number and `false` otherwise.
+
+**Note :** A prime number is a natural integer which admits exactly two distinct positive divisors. (1 and itself). Example: 2, 3, 5, 7, 11, 13, 17, 19 ...
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== is-valid-array-subsequence ===
+# is-valid-array-subsequence
+
+Created by [@theoludwig](https://github.com/theoludwig) on 23 April 2022.
+
+## Instructions
+
+Given two non-empty arrays of integers, write a function that determines whether the second array is a subsequence of the first one.
+
+A subsequence of an array is a set of numbers that aren't necessarily adjacent in the array but that are in the same order as they appear in the array. For instance, the numbers `[1, 3, 4]` form a subsequence of the array `[1, 2, 3, 4]`, and so do the numbers `[2, 4]`. Note that a single number in an array and the array itself are both valid subsequences of the array.
+
+### Input
+
+- **Line 1:** `array` Integers separated by spaces
+- **Line 2:** `sequence` Integers separated by spaces
+
+### Output
+
+The output should return `true` if the `sequence` is a subsequence of `array` and `false` otherwise.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+5 1 22 25 6 -1 8 10
+1 6 -1 10
+```
+
+#### Output
+
+```txt
+true
+```
+
+### Example 2
+
+#### Input
+
+```txt
+5 1 22 25 6 -1 8 10
+5 1 22 25 6 -1 8 10 12
+```
+
+#### Output
+
+```txt
+false
+```
+
+
+=== left-pad ===
+# left-pad
+
+Created by [@theoludwig](https://github.com/theoludwig) on 21 May 2023.
+
+## Instructions
+
+Create a function that pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. The padding is applied from the start (left) of the current string.
+
+Inspired from [left-pad (JavaScript npm package)](https://www.npmjs.com/package/left-pad).
+
+### Input
+
+- **Line 1:** The current string
+- **Line 2:** The length of the resulting string
+- **Line 3:** The string to pad the current string with
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+foo
+12
+-
+```
+
+#### Output
+
+```txt
+---------foo
+```
+
+
+=== look-and-say-sequence-conway ===
+# look-and-say-sequence-conway
+
+Created by [@theoludwig](https://github.com/theoludwig) on 30 November 2021.
+
+## Instructions
+
+In mathematics, the **look-and-say sequence** is the sequence of integers beginning as follows: `1, 11, 21, 1211, 111221, 312211, 13112221, 1113213211, ...`.
+
+The look-and-say sequence was introduced and analyzed by John **Conway**.
+
+To generate a member of the sequence from the previous member, read off the digits of the previous member, counting the number of digits in groups of the same digit. For example:
+
+- `1` is read off as "one 1" or 11.
+- `11` is read off as "two 1s" or 21.
+- `21` is read off as "one 2, then one 1" or 1211.
+- `1211` is read off as "one 1, one 2, then two 1s" or 111221.
+- `111221` is read off as "three 1s, two 2s, then one 1" or 312211.
+
+Write a program that prints the next term of the **look-and-say sequence**.
+
+## Source
+
+[Look-and-say sequence - Wikipedia](https://en.wikipedia.org/wiki/Look-and-say_sequence)
+
+## Examples
+
+### Example 1
+
+#### Input
+
+```txt
+11
+```
+
+#### Output
+
+```txt
+21
+```
+
+### Example 2
+
+#### Input
+
+```txt
+1211
+```
+
+#### Output
+
+```txt
+111221
+```
+
+See the `test` folder for examples of input/output.
+
+
+=== maximum-subarray-sum ===
+# maximum-subarray-sum
+
+Created by [@theoludwig](https://github.com/theoludwig) on 1 May 2022.
+
+## Instructions
+
+Given an array of `n` integers, find the contiguous subarray with the largest sum.
+
+Contiguous subarray is any sub series of elements in a given array that are contiguous ie their indices are continuous. The problem is interesting when there may be negative values in the array, because if the array only contains positive values, the maximum subarray sum is basically the sum of the array (the subarray being the complete array).
+
+## Input
+
+- **Line 1:** An integer `n` for the length of the list of integers
+- **`n` next lines:** the integers
+
+## Output
+
+The largest sum of a contiguous subarray.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+6
+1
+2
+3
+4
+5
+6
+```
+
+#### Output
+
+```txt
+21
+```
+
+**Explanation:** The subarray with the largest sum is the array itself (as there is no negative values) `[1, 2, 3, 4, 5, 6]` which has a sum of `21`.
+
+### Example 2
+
+#### Input
+
+```txt
+8
+-1
+2
+4
+-3
+5
+2
+-5
+2
+```
+
+#### Output
+
+```txt
+10
+```
+
+**Explanation:** The subarray with the largest sum is `[2, 4, -3, 5, 2]` which has a sum of `10`.
+
+
+=== offset-arrays ===
+# offset-arrays
+
+Created by [@theoludwig](https://github.com/theoludwig) on 29 June 2021.
+
+## Instructions
+
+### Goal
+
+To settle the debate of 0-based vs 1-based indexing I have created a language where you must explicitly state the range of indices an array should have.
+
+For example, given an array definition "A[-1..1] = 1 2 3", you would have:
+
+- A[-1] = 1
+- A[0] = 2
+- A[1] = 3
+
+You are given a list of `n` array definitions and your job is to figure out what number is found in a given index `i` of an array `arr`. Note that the indexing operations may be nested (in the above example, A[A[-1]] would produce result 3).
+
+### Input
+
+- **Line 1:** An integer `n` for the number of array assignments
+- **`n` next lines:** One array assignment per line: `array_identifier` [ `first_index` .. `last_index` ] = `last_index - first_index + 1` integers separated by space
+- **Line `n+2`:** Element to print: `arr` [ `i` ]
+
+### Constraints
+
+- $$1 \leq n \leq 100$$
+- Array names consist only of uppercase letters A to Z.
+- Array lengths are between 1 and 100 (no empty arrays).
+- Indexing operations have at most 50 levels of nesting.
+- Indices are always within bounds in the test cases.
+
+## Source
+
+[CodinGame](https://www.codingame.com/ide/puzzle/offset-arrays)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+3
+A[-1..1] = 1 2 3
+B[3..7] = 3 4 5 6 7
+C[-2..1] = 1 2 3 4
+A[0]
+```
+
+#### Output
+
+```txt
+2
+```
+
+
+=== prefix-suffix ===
+# prefix-suffix
+
+Created by [@theoludwig](https://github.com/theoludwig) on 2 December 2021.
+
+## Instructions
+
+A prefix is an affix which is placed before the stem of a word. Adding it to the beginning of one word changes it into another word. For example, when the prefix un- is added to the word happy, it creates the word unhappy.
+
+A suffix is an affix which is placed after the stem of a word. Common examples are case endings, which indicate the grammatical case of nouns, adjectives, and verb endings, which form the conjugation of verbs. Suffixes can carry grammatical information or lexical information.
+
+Write a programs that takes 2 strings ("words") and prints if one is a prefix/suffix of the other.
+
+### Input
+
+- **Line 1:** The word to be checked
+- **Line 2:** The potential prefix/suffix
+
+### Output
+
+- **Line 1:** `true` if the second word is a **prefix** of the first, `false` otherwise
+- **Line 1:** `true` if the second word is a **suffix** of the first, `false` otherwise
+
+## Sources
+
+- [Wikipedia - Prefix](https://en.wikipedia.org/wiki/Prefix)
+- [Wikipedia - Suffix](https://en.wikipedia.org/wiki/Suffix)
+
+## Examples
+
+### Example 1
+
+#### Input
+
+```txt
+Py
+AlgoPy
+```
+
+#### Output
+
+```txt
+false
+false
+```
+
+### Example 2
+
+#### Input
+
+```txt
+AlgoPy
+Py
+```
+
+#### Output
+
+```txt
+false
+true
+```
+
+### Example 3
+
+#### Input
+
+```txt
+same-word
+same-word
+```
+
+#### Output
+
+```txt
+true
+true
+```
+
+See the `test` folder for examples of input/output.
+
+
+=== prime-numbers-decomposition ===
+# prime-numbers-decomposition
+
+Created by [@theoludwig](https://github.com/theoludwig) on 16 October 2021.
+
+## Instructions
+
+## Definition
+
+In mathematics, product decomposition of prime factors (also known as integer factorization into prime numbers) involves writing a strictly positive integer as a product of prime numbers.
+
+This factorization is unique and exists for all numbers and has many applications, particularly in RSA cryptography.
+
+**Note :** A prime number is a natural integer which admits exactly two distinct positive divisors. (1 and itself). Example: 2, 3, 5, 7, 11, 13, 17, 19...
+
+## How to decompose a number into a product of factors of prime numbers?
+
+To find the product decomposition of prime factors of a number `N`, there is no mathematical formula. To achieve this, there are algorithms, the most basic of which attempts to divide the number `N` by the set of prime factors `p` which are less than `N`.
+If `p` is a divisor of `N` then start again by taking a new `N = N / p` as long as there are possible prime divisors.
+
+## Examples
+
+### Example
+
+#### Input
+
+```txt
+32
+```
+
+#### Output
+
+```txt
+2 * 2 * 2 * 2 * 2
+```
+
+See the `test` folder for examples of input/output.
+
+
+=== print-pyramid ===
+# print-pyramid
+
+Created by [@theoludwig](https://github.com/theoludwig) on 21 September 2021.
+
+## Instructions
+
+Display a pyramid of stars (`*`) whose height is given and in the right order (`normal` or `reverse`).
+
+### Input
+
+- **Line 1:** The string : `normal` or `reverse` to determine how to show the pyramid.
+- **Line 2:** The integer : height of the pyramid.
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== reverse-polish-notation ===
+# reverse-polish-notation
+
+Created by [@theoludwig](https://github.com/theoludwig) on 29 September 2020.
+
+## Instructions
+
+Your job is to create a calculator which evaluates expressions in Reverse Polish notation (a mathematical notation in which operators follow their operands. It does not need any parentheses as long as each operator has a fixed number of operands).
+
+For example expression 5 3 + (which is equivalent to 5 + 3 in normal notation) should evaluate to 8.
+
+For your convenience, the input is formatted such that a space is provided between every token.
+
+Empty expression should evaluate to 0.
+
+Valid operations are +, -, \*, /.
+
+You may assume that there won't be exceptional situations (like stack underflow or division by zero).
+
+All the numbers are integers; you don't need to worry about floating point numbers.
+
+## Source
+
+[Reverse polish notation - Codewars](https://www.codewars.com/kata/52f78966747862fc9a0009ae)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== roman-numerals ===
+# roman-numerals
+
+Created by [@theoludwig](https://github.com/theoludwig) on 30 June 2021.
+
+## Instructions
+
+The objective of this challenge is to create a function that translates a number into Roman numerals or the other way around.
+
+We will use the letters `I`, `V`, `X`, `L`, `C`, `D`, `M` to build the Roman numerals.
+
+Here are the rules for building a Roman numeral:
+
+- The numbers `1`, `2` and `3` are written respectively as `I`, `II` and `III`
+- The number `5` is written as `V`
+- The number `10` is written as `X`
+- The number `50` is written as `L`
+- The number `100` is written as `C`
+- The number `500` is written as `D`
+- The number `1000` is written as `M`
+- When writing two letters in a row, if the numerical value of the first is greater than the numerical value of the second, their numerical values ​​are added. For example the number `6` is written `VI`. We add `V` (5) + `I` (1) = 6.
+- When writing two letters in a row, if the numerical value of the first is less than the numerical value of the second, the value of the first is subtracted from the second. For example the number `4` is written `IV`. We subtract `V` (5) - `I` (1) = 4.
+- Subtractions of values ​​are limited to 2 letters only. For example we **cannot** write `8` while doing `IIX`. We must use the addition of letters like this `VIII`.
+- Therefore, the first ten numbers are written as `I`, `II`, `III`, `IV`, `V`, `VI`, `VII`, `VIII`, `IX`, `X` . Larger numbers follow the same pattern.
+- You can associate as many symbols as you want to write larger numbers, for example:
+    - `36` is written as `XXXVI`
+    - `42` is written as `XLII`
+    - `2448` is written as `MMCDXLVIII`.
+
+| Symbol | I   | V   | X   | L   | C   | D   | M    |
+| ------ | --- | --- | --- | --- | --- | --- | ---- |
+| Value  | 1   | 5   | 10  | 50  | 100 | 500 | 1000 |
+
+### Input
+
+- **Line 1:** The string : `arabic to roman` or `roman to arabic` to determine how to convert the number
+- **Line 2:** The number to convert
+
+## Sources
+
+- [Wikipedia - Roman numerals](https://en.wikipedia.org/wiki/Roman_numerals)
+- [Wikipedia - Arabic numerals](https://en.wikipedia.org/wiki/Arabic_numerals)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== rotate-2-dimensional-array-90-degrees ===
+# rotate-2-dimensional-array-90-degrees
+
+Created by [@theoludwig](https://github.com/theoludwig) on 3 December 2021.
+
+## Instructions
+
+Given a square/rectangle matrix representing an image and a direction of rotation (`clockwise` or `anticlockwise`), rotate the image by 90 degrees.
+
+### Input
+
+- **Line 1:** The direction (`clockwise` or `anticlockwise`) of rotation
+- **Next Lines:** The matrix of the image
+
+### Output
+
+- **Lines:** The rotated matrix
+
+## Examples
+
+### Example 1
+
+#### Input
+
+```txt
+clockwise
+1 2 3
+4 5 6
+7 8 9
+```
+
+#### Output
+
+```txt
+7 4 1
+8 5 2
+9 6 3
+```
+
+### Example 2
+
+#### Input
+
+```txt
+anticlockwise
+1 2 3
+4 5 6
+7 8 9
+```
+
+#### Output
+
+```txt
+1 4 7
+2 5 8
+3 6 9
+```
+
+See the `test` folder for examples of input/output.
+
+
+=== single-number ===
+# single-number
+
+Created by [@theoludwig](https://github.com/theoludwig) on 21 August 2023.
+
+## Instructions
+
+Given a **non-empty** array of integers, every element appears twice except for one. Find that single one.
+
+You must implement a solution with a linear runtime complexity and use only constant extra space.
+
+### Constraints
+
+- $$1 \leq numbers.length \leq 3 \times 10^4$$
+- $$-3 \times 10^4 \leq numbers[index] \leq 3 \times 10^4$$
+- Each element in the array appears twice except for one element which appears only once.
+
+## Source
+
+[LeetCode - Single Number](https://leetcode.com/problems/single-number/)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+4
+1
+2
+1
+2
+```
+
+#### Output
+
+```txt
+4
+```
+
+
+=== slugify ===
+# slugify
+
+Created by [@theoludwig](https://github.com/theoludwig) on 10 November 2021.
+
+## Instructions
+
+Write a function that generates a slug from a string.
+
+A Slug is the unique identifying part of a web address, typically at the end of the URL.
+
+The rules for generating a slug are as follows (`kebab-case`):
+
+- Replace spaces with hyphens.
+- Remove all non-alphanumeric characters.
+
+## Examples
+
+### Example 1
+
+#### Input
+
+```txt
+hello world
+```
+
+#### Output
+
+```txt
+hello-world
+```
+
+### Example 2
+
+#### Input
+
+```txt
+--hello world--
+```
+
+### Output
+
+```txt
+hello-world
+```
+
+### Example 3
+
+#### Input
+
+```txt
+😄 emoji
+```
+
+### Output
+
+```txt
+emoji
+```
+
+See the `test` folder for examples of input/output.
+
+
+=== sorting-algorithms ===
+# sorting-algorithms
+
+Created by [@theoludwig](https://github.com/theoludwig) on 29 June 2021.
+
+## Instructions
+
+In computer science, a sorting algorithm is an algorithm that puts elements of a list in a certain order.
+We will use the [numerical order](https://en.wikipedia.org/wiki/Numerical_order).
+
+Write a function that takes a list of integers and sort them in ascending order.
+
+## Input
+
+- **Line 1:** An integer $n$ for the length of the list of integers
+- **$n$ next lines:** the numbers to sort
+
+### Constraints
+
+- $$n \leq 25 000$$
+
+## Source
+
+[Wikipedia - Sorting algorithm](https://en.wikipedia.org/wiki/Sorting_algorithm)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== sudoku ===
+# sudoku
+
+Created by [@theoludwig](https://github.com/theoludwig) on 6 July 2021.
+
+## Instructions
+
+Sudoku is a logic-based, combinatorial number-placement puzzle.
+
+The objective is to fill a 9×9 grid with digits so that each column, each row, and each of the nine 3×3 subgrids that compose the grid (also called "boxes", "blocks", or "regions") contains all of the digits from 1 to 9. The puzzle setter provides a partially completed grid, which for a well-posed puzzle has a single solution.
+
+You can't use the same numbers twice in a:
+
+- row
+- column
+- square of 3x3
+
+Write a program that solves the Sudoku given in input.
+
+The empty cells are represented by 0.
+
+## Source
+
+[Wikipedia - Sudoku](https://en.wikipedia.org/wiki/Sudoku)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+5 3 0 0 7 0 0 0 0
+6 0 0 1 9 5 0 0 0
+0 9 8 0 0 0 0 6 0
+8 0 0 0 6 0 0 0 3
+4 0 0 8 0 3 0 0 1
+7 0 0 0 2 0 0 0 6
+0 6 0 0 0 0 2 8 0
+0 0 0 4 1 9 0 0 5
+0 0 0 0 8 0 0 7 9
+```
+
+#### Output
+
+```txt
+5 3 4 6 7 8 9 1 2
+6 7 2 1 9 5 3 4 8
+1 9 8 3 4 2 5 6 7
+8 5 9 7 6 1 4 2 3
+4 2 6 8 5 3 7 9 1
+7 1 3 9 2 4 8 5 6
+9 6 1 5 3 7 2 8 4
+2 8 7 4 1 9 6 3 5
+3 4 5 2 8 6 1 7 9
+```
+
+
+=== triangle-type ===
+# triangle-type
+
+Created by [@theoludwig](https://github.com/theoludwig) on 30 June 2021.
+
+## Instructions
+
+Given the lengths of the 3 sides of a triangle, your function should return whether it is `equilateral`, `isosceles`, `scalene` or `impossible`.
+
+- A triangle is `equilateral` when its 3 sides are equal
+- A triangle is `isosceles` when 2 of its sides are equal
+- A triangle is `scalene` when none of its sides is equal to another side
+- A triangle is `impossible` when the sum of two of its sides is strictly less than the third side
+
+## Input
+
+- **Line 1 to 3:** The length of each side of the triangle
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+
+=== valid-parentheses ===
+# valid-parentheses
+
+Created by [@theoludwig](https://github.com/theoludwig) on 18 November 2024.
+
+## Instructions
+
+Given a string containing just the characters `'('`, `')'`, `'{'`, `'}'`, `'['` and `']'`, determine if the input string is valid.
+
+An input string is valid if:
+
+- Open brackets must be closed by the same type of brackets.
+- Open brackets must be closed in the correct order.
+- Every close bracket has a corresponding open bracket of the same type.
+
+## Source
+
+[LeetCode - Valid Parentheses](https://leetcode.com/problems/valid-parentheses)
+
+## Examples
+
+See the `test` folder for examples of input/output.
+
+### Example 1
+
+#### Input
+
+```txt
+()
+```
+
+#### Output
+
+```txt
+true
+```
+
+### Example 2
+
+#### Input
+
+```txt
+(]
+```
+
+#### Output
+
+```txt
+false
+```
+
Index: backend/challenges/initialChallenges.json
===================================================================
--- backend/challenges/initialChallenges.json	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
+++ backend/challenges/initialChallenges.json	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
@@ -0,0 +1,411 @@
+[
+  {
+    "title": "a-phone-code",
+    "description": "Your task is to calculate the length of the longest common starting sequence (prefix) among a list of phone numbers, which represents the city's phone code.",
+    "examples": [
+      {
+        "input": "3\n007\n00123\n00124",
+        "output": "2"
+      },
+      {
+        "input": "4\n12345\n123\n123987\n123456",
+        "output": "3"
+      }
+    ],
+    "testcases": [
+      {
+        "input": "12\n5551234\n5551235\n5551236\n5551237\n5551238\n5551239\n5551240\n5551241\n5551242\n5551243\n5551244\n5551245",
+        "output": "5"
+      },
+      {
+        "input": "10\n9876543\n9876544\n9876545\n9876546\n9876547\n9876548\n9876549\n9876540\n9876541\n9876542",
+        "output": "6"
+      },
+      {
+        "input": "15\n4441111\n4442222\n4443333\n4444444\n4445555\n4446666\n4447777\n4448888\n4449999\n4440000\n4441234\n4445678\n4449012\n4443456\n4447890",
+        "output": "3"
+      },
+      {
+        "input": "11\n12345\n12346\n12347\n12348\n12349\n12340\n12341\n12342\n12343\n67890\n98765",
+        "output": "0"
+      },
+      {
+        "input": "14\n807123\n807124\n807125\n807126\n807127\n807128\n807129\n807130\n807131\n807132\n807133\n807134\n807135\n807136",
+        "output": "4"
+      },
+      {
+        "input": "10\n12345\n23456\n34567\n45678\n56789\n67890\n78901\n89012\n90123\n01234",
+        "output": "0"
+      },
+      {
+        "input": "13\n5551234567\n5551234568\n5551234569\n5551234560\n5551234561\n5551234562\n5551234563\n5551234564\n5551234565\n5551234566\n5551234577\n5551234588\n5551234599",
+        "output": "8"
+      },
+      {
+        "input": "15\n3141592653\n3141592654\n3141592655\n3141592656\n3141592657\n3141592658\n3141592659\n3141592650\n3141592651\n3141592652\n3141592660\n3141592661\n3141592662\n3141592663\n3141592664",
+        "output": "8"
+      },
+      {
+        "input": "12\n9998887770\n9998887771\n9998887772\n9998887773\n9998887774\n9998887775\n9998887776\n9998887777\n9998887778\n9998887779\n9998887780\n9998887781",
+        "output": "8"
+      },
+      {
+        "input": "10\n1111111111\n1111111112\n1111111113\n1111111114\n1111111115\n1111111116\n1111111117\n1111111118\n1111111119\n1111111110",
+        "output": "9"
+      }
+    ],
+    "difficulty": "Easy",
+    "output_type": "integer"
+  },
+  {
+    "title": "acronyms",
+    "description": "Develop a function that takes a sentence and converts it into its acronym by taking the first letter of each word.",
+    "examples": [
+      {
+        "input": "Programming Challenges is really cool",
+        "output": "PCIRC"
+      },
+      {
+        "input": "Portable Network Graphics",
+        "output": "PNG"
+      }
+    ],
+    "testcases": [
+      {
+        "input": "Powerful Networked Graphics solutions deliver exceptional visualization capabilities for complex three-dimensional renderings with advanced lighting models that simulate realistic surface properties while optimizing computational resources through sophisticated algorithms designed by leading experts in computer graphics rendering technology across multiple industrial applications.",
+        "output": "PNGSDEVCCFTDRWALMTSRSPWOCRTSBALDEICRGTAMIA"
+      },
+      {
+        "input": "Hypertext Transfer Markup Language fundamentally revolutionized digital communications by establishing standardized document formatting protocols that enable cross-platform compatibility across diverse operating systems while supporting embedded media elements alongside interactive scripting capabilities through comprehensive browser-based rendering engines that continuously evolve with advancing web technologies.",
+        "output": "HTMLFRDCBESTDCPEDSMEISCTCBRETCEWT"
+      },
+      {
+        "input": "furthermore yesterday's investigation revealed critical market intelligence suggesting significant downward trends affecting quarterly projections across multiple business units particularly within international divisions operating under regulatory constraints while domestic operations continue showing resilience despite supply chain disruptions affecting manufacturing capabilities throughout north american distribution networks.",
+        "output": "FYIRCMISSDTAQPAMBUPWIDOURWDOCSRDSCDAMCTNDN"
+      },
+      {
+        "input": " linguistic analysis through sophisticated computational models represents fundamental advancements in natural language processing techniques enabling accurate machine translation systems while improving contextual understanding of semantic relationships between complex sentence structures across multiple languages regardless of syntactic variations commonly encountered in diverse cultural expressions of human communication  ",
+        "output": "LATSCMRFAINLPTEAMTSWICUOSRBCSSACMLROSVCEIDCEHC"
+      },
+      {
+        "input": "modern software business works through integrated development environments utilizing continuous integration pipelines with automated testing frameworks that enhance code quality while reducing deployment times across distributed systems architectures supporting microservices implementations for scalable enterprise applications requiring minimal downtime during updates throughout production environments.",
+        "output": "MSBWTIDEVUCIPWATFTECQWRDTADSASMIFSEARMDDUTE"
+      },
+      {
+        "input": "Automated System Workflows dramatically improve organizational efficiency by streamlining repetitive business processes through intelligent routing mechanisms that distribute tasks according to established priority levels while monitoring completion metrics against predetermined benchmarks ensuring optimal resource allocation throughout departments regardless of geographical distribution across multiple international office locations.",
+        "output": "ASWDIOEBSRBPTIRMTDTATEPLWMCMAPBESORTDROGDAMI"
+      },
+      {
+        "input": "PHP: Hypertext Preprocessor remains remarkably relevant in modern web development ecosystems despite emerging alternatives because its extensive library ecosystem provides developers with battle-tested solutions for common challenges while maintaining backward compatibility across versions ensuring legacy applications continue functioning alongside newer implementations throughout evolving technology landscapes.",
+        "output": "PHPRRIMWDEDAEBITELPDBTSCCWMBCAVELALCFANITEL"
+      },
+      {
+        "input": "Fundamental Information Flow Operations represent critical architectural components in distributed computing systems where data sequencing maintains transactional integrity throughout asynchronous processing environments while preventing race conditions that could otherwise compromise system stability during peak operational periods requiring careful implementation considerations especially within memory-constrained embedded computing platforms.",
+        "output": "FIFOERCACIDCSWTMTITAPEPRCTCOCSSPOPRCICCEWM"
+      },
+      {
+        "input": "Accelerated System Architecture Processing technology delivers unprecedented computational throughput for data-intensive applications requiring real-time analysis of streaming information sources while maintaining exceptionally low latency responses necessary for mission-critical operations where millisecond delays could potentially result in significant financial implications or compromised safety protocols within industrial control systems.",
+        "output": "ASAPTDUCTFDIARRTASISWMELLRNFMCWMDCPRIFSICPWIS"
+      },
+      {
+        "input": "wireless wide networks 1st generation 2nd generation 3rd generation technologies evolved dramatically through decades of telecommunications research establishing foundations for modern connectivity paradigms while overcoming significant technical limitations through innovative spectrum utilization techniques alongside increasingly sophisticated modulation approaches that maximize data throughput within constrained bandwidth allocations supporting exponential growth in connected devices worldwide.",
+        "output": "WWN123GETDTDOTREFMCPWOSTLTISUTALISMTWCBANNCE"
+      }
+    ],
+    "difficulty": "Easy",
+    "output_type": "string"
+  },
+  {
+    "title": "caesar-cipher",
+    "description": "Implement a function that encrypts a message using the Caesar cipher technique, which involves shifting each letter of the alphabet by a specified number of places.",
+    "examples": [
+      {
+        "input": "'ANTHONY', -3",
+        "output": "XKQELKV"
+      },
+      {
+        "input": "'JULIUS CAESAR', 3",
+        "output": "MXOLXV FDHVDU"
+      }
+    ],
+    "testcases": [
+      {
+        "input": "'HELLO', 3",
+        "output": "KHOOR"
+      },
+      {
+        "input": "'XYZ', 3",
+        "output": "ABC"
+      },
+      {
+        "input": "'ABC', -3",
+        "output": "XYZ"
+      },
+      {
+        "input": "'The quick brown fox jumps over the lazy dog', 13",
+        "output": "Gur dhvpx oebja sbk whzcf bire gur ynml qbt"
+      },
+      {
+        "input": "'middle-Outz', 2",
+        "output": "okffng-Qwvb"
+      },
+      {
+        "input": "'No Change', 0",
+        "output": "No Change"
+      },
+      {
+        "input": "'Big shift!', 75",
+        "output": "Elj vkliw!"
+      },
+      {
+        "input": "'Negative Wrap!', -2",
+        "output": "LcEXPLGTc YpYn!"
+      },
+      {
+        "input": "'Veni, Vidi, Vici', -10",
+        "output": "Ludq, Lsds, Lsgs"
+      },
+      {
+        "input": "'All lowercase', 5",
+        "output": "Fqq qtbjwhfxj"
+      }
+    ],
+    "difficulty": "Easy",
+    "output_type": "string"
+  },
+  {
+    "title": "cakes",
+    "description": "You need to determine the maximum number of cakes you can bake given a list of required ingredients per cake and the quantities of those ingredients you currently possess.Line 1: Single integer N for the number of ingredients. N next lines: One for each ingredient. Each of these lines contains two positive integers: the first one is the required quantity of this ingredient per cake, the second one is the quantity of this ingredient you have in your kitchen.",
+    "examples": [
+      {
+        "input": "3\n100 500\n2 5\n70 1000",
+        "output": "2"
+      },
+      {
+        "input": "3\n100 50\n2 5\n70 1000",
+        "output": "0"
+      }
+    ],
+    "testcases": [
+      {
+        "input": "10\n2 20\n3 33\n5 100\n7 77\n11 121\n13 130\n17 170\n19 190\n23 230\n29 290",
+        "output": "10"
+      },
+      {
+        "input": "12\n1 1000\n2 2000\n3 3000\n4 4000\n5 5000\n6 6000\n7 7000\n8 8000\n9 9000\n10 10000\n11 11000\n12 12000",
+        "output": "83"
+      },
+      {
+        "input": "15\n100 1000\n200 1500\n300 900\n400 800\n500 2500\n600 3600\n700 4900\n800 6400\n900 8100\n1000 10000\n1100 12100\n1200 14400\n1300 16900\n1400 19600\n1500 22500",
+        "output": "3"
+      },
+      {
+        "input": "18\n5 100\n10 200\n15 300\n20 400\n25 500\n30 600\n35 700\n40 800\n45 900\n50 1000\n55 1100\n60 1200\n65 1300\n70 1400\n75 1500\n80 1600\n85 1700\n90 1800",
+        "output": "20"
+      },
+      {
+        "input": "14\n7 70\n14 140\n21 210\n28 280\n35 350\n42 420\n49 490\n56 560\n63 630\n70 700\n77 770\n84 840\n91 910\n98 980",
+        "output": "10"
+      },
+      {
+        "input": "11\n100 1000\n200 2000\n300 3000\n400 4000\n500 5000\n600 6000\n700 7000\n800 8000\n900 9000\n1000 10000\n1100 11000",
+        "output": "10"
+      },
+      {
+        "input": "13\n2 100\n3 150\n4 200\n5 250\n6 300\n7 350\n8 400\n9 450\n10 500\n11 550\n12 600\n13 650\n14 700",
+        "output": "50"
+      },
+      {
+        "input": "16\n1 100\n2 200\n3 300\n4 400\n5 500\n6 600\n7 700\n8 800\n9 900\n10 1000\n11 1100\n12 1200\n13 1300\n14 1400\n15 1500\n16 1600",
+        "output": "100"
+      },
+      {
+        "input": "17\n10 100\n20 200\n30 300\n40 400\n50 500\n60 600\n70 700\n80 800\n90 900\n100 1000\n110 1100\n120 1200\n130 1300\n140 1400\n150 1500\n160 1600\n170 1700",
+        "output": "10"
+      },
+      {
+        "input": "20\n1 1000\n2 2000\n3 3000\n4 4000\n5 5000\n6 6000\n7 7000\n8 8000\n9 9000\n10 10000\n11 11000\n12 12000\n13 13000\n14 14000\n15 15000\n16 16000\n17 17000\n18 18000\n19 19000\n20 20000",
+        "output": "50"
+      }
+    ],
+    "difficulty": "Easy",
+    "output_type": "integer"
+  },
+
+  {
+    "title": "consecutive-numbers",
+    "description": "Design a function that identifies and returns all sequences of consecutive integers within a given list of numbers. The required length for a sequence to be considered 'consecutive' is given as the first input. Note that output sequences can contain numbers which are not consecutive in the input list",
+    "examples": [
+      {
+        "input": "2\n5 ; 1 ; 2 ; 3 ; 8 ; -5 ; -4 ; 7",
+        "output": "1 ; 2\n2 ; 3\n-5 ; -4"
+      },
+      {
+        "input": "3\n5 ; 1 ; 2 ; 3 ; 8 ; -5 ; -4 ; 7",
+        "output": "1 ; 2 ; 3"
+      }
+    ],
+    "testcases": [
+      {
+        "input": "3\n10 1 5 2 6 3 7 4 8",
+        "output": "1 2 3\n2 3 4\n3 4 5\n4 5 6\n5 6 7\n6 7 8"
+      },
+      {
+        "input": "4\n-5 0 -4 1 -3 2 -2 3 -1",
+        "output": "-5 -4 -3 -2\n-4 -3 -2 -1\n-3 -2 -1 0\n-2 -1 0 1\n-1 0 1 2\n0 1 2 3"
+      },
+      {
+        "input": "2\n100 50 101 51 102 52 103",
+        "output": "50 51\n51 52\n100 101\n101 102\n102 103"
+      },
+      {
+        "input": "5\n20 1 19 2 18 3 17 4 16 5 15",
+        "output": "1 2 3 4 5\n15 16 17 18 19\n16 17 18 19 20"
+      },
+      {
+        "input": "3\n0 10 -1 9 -2 8 -3 7 -4 6 -5",
+        "output": "-5 -4 -3\n-4 -3 -2\n-3 -2 -1\n6 7 8\n7 8 9\n8 9 10"
+      },
+      {
+        "input": "4\n7 1 8 2 9 3 10 4 11 5 12 6",
+        "output": "1 2 3 4\n2 3 4 5\n3 4 5 6\n7 8 9 10\n8 9 10 11\n9 10 11 12"
+      },
+      {
+        "input": "2\n1 10 2 9 3 8 4 7 5 6",
+        "output": "1 2\n2 3\n3 4\n4 5\n5 6\n6 7\n7 8\n8 9\n9 10"
+      },
+      {
+        "input": "6\n-10 0 -9 1 -8 2 -7 3 -6 4 -5 5 -4",
+        "output": "-10 -9 -8 -7 -6 -5\n-9 -8 -7 -6 -5 -4\n0 1 2 3 4 5"
+      },
+      {
+        "input": "3\n50 40 30 51 41 31 52 42 32 53 43 33",
+        "output": "30 31 32\n31 32 33\n40 41 42\n41 42 43\n50 51 52\n51 52 53"
+      },
+      {
+        "input": "4\n15 1 14 2 13 3 12 4 11 5 10 6 9 7 8",
+        "output": "1 2 3 4\n2 3 4 5\n3 4 5 6\n4 5 6 7\n5 6 7 8\n6 7 8 9\n7 8 9 10\n8 9 10 11\n9 10 11 12\n10 11 12 13\n11 12 13 14\n12 13 14 15"
+      }
+    ],
+    "difficulty": "Medium",
+    "output_type": "string"
+  },
+
+  {
+    "title": "fibonacci",
+    "description": "Your goal is to build a function that generates an array containing a specified quantity of Fibonacci numbers. The Fibonacci sequence starts with 0 and 1, and each subsequent number is the sum of the two preceding ones.",
+    "examples": [
+      {
+        "input": "8",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13]"
+      },
+      {
+        "input": "14",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]"
+      }
+    ],
+    "testcases": [
+      {
+        "input": "25",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368]"
+      },
+      {
+        "input": "30",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229]"
+      },
+      {
+        "input": "18",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597]"
+      },
+      {
+        "input": "22",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946]"
+      },
+      {
+        "input": "35",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887]"
+      },
+      {
+        "input": "12",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]"
+      },
+      {
+        "input": "28",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418]"
+      },
+      {
+        "input": "16",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]"
+      },
+      {
+        "input": "33",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309]"
+      },
+      {
+        "input": "19",
+        "output": "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]"
+      }
+    ],
+    "difficulty": "Easy",
+    "output_type": "array"
+  },
+
+  {
+    "title": "first-non-repeating-character",
+    "description": "Write a function to find the first character in a string that does not appear again in that string. If every character is repeated, the function should return an empty string.",
+    "examples": [
+      {
+        "input": "'stress'",
+        "output": "'t'"
+      },
+      {
+        "input": "'aabbcce'",
+        "output": "'e'"
+      }
+    ],
+    "testcases": [
+      {
+        "input": "'abacabadabacabadabacabaeabacabadabacabadabacabadabacabad'",
+        "output": "'e'"
+      },
+      {
+        "input": "'abcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcbaabcdefghijklmnopqrstuvwxy1z'",
+        "output": "'1'"
+      },
+      {
+        "input": "'thequickbrownfoxjumpsoverthelazydogthequickbrownfoxjumpsoverthelazydogx'",
+        "output": "'x'"
+      },
+      {
+        "input": "'aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzzabcdefghijklmnopqrstuvwxyz'",
+        "output": "'a'"
+      },
+      {
+        "input": "'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyx'",
+        "output": "'x'"
+      },
+      {
+        "input": "'1bcdefghijklmnopqrstuvwxyzaabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz'",
+        "output": "'1'"
+      },
+      {
+        "input": "'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcf'",
+        "output": "'f'"
+      },
+      {
+        "input": "'qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmz'",
+        "output": "'z'"
+      },
+      {
+        "input": "'xxyyzzwwvvuuttssrrqqppoonnmmllkkjjiihhggffeeddccbbaa1'",
+        "output": "'1'"
+      },
+      {
+        "input": "'mnbvcxzlkjhgfdsapoiuytrewqmnbvcxzlkjhgfdsapoiuytrewqx'",
+        "output": "'x'"
+      }
+    ],
+    "difficulty": "Medium",
+    "output_type": "string"
+  }
+]
Index: backend/models/Challenge.js
===================================================================
--- backend/models/Challenge.js	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
+++ backend/models/Challenge.js	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
@@ -0,0 +1,14 @@
+class Challenge {
+  constructor(data = {}) {
+    this.id = data.id;
+    this.title = data.title || '';
+    this.content = data.content || '';
+    this.solving_date = data.solving_date;
+    this.attempted_by = data.attempted_by;
+    this.solved_by = data.solved_by;
+    this.expired = data.expired || false;
+    this.examples = data.examples;
+  }
+}
+
+module.exports = Challenge;
Index: backend/node_modules/.package-lock.json
===================================================================
--- backend/node_modules/.package-lock.json	(revision ce371e5a1f811d4ff62f84fbd74dbef9a2b668f3)
+++ backend/node_modules/.package-lock.json	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
@@ -130,4 +130,21 @@
       }
     },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "license": "MIT"
+    },
+    "node_modules/axios": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
+      "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
+      "license": "MIT",
+      "dependencies": {
+        "follow-redirects": "^1.15.6",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
+      }
+    },
     "node_modules/balanced-match": {
       "version": "1.0.2",
@@ -184,4 +201,10 @@
       }
     },
+    "node_modules/boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+      "license": "ISC"
+    },
     "node_modules/brace-expansion": {
       "version": "1.1.11",
@@ -244,4 +267,280 @@
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/cheerio": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
+      "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==",
+      "license": "MIT",
+      "dependencies": {
+        "cheerio-select": "^2.1.0",
+        "dom-serializer": "^2.0.0",
+        "domhandler": "^5.0.3",
+        "domutils": "^3.1.0",
+        "encoding-sniffer": "^0.2.0",
+        "htmlparser2": "^9.1.0",
+        "parse5": "^7.1.2",
+        "parse5-htmlparser2-tree-adapter": "^7.0.0",
+        "parse5-parser-stream": "^7.1.2",
+        "undici": "^6.19.5",
+        "whatwg-mimetype": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=18.17"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+      "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "boolbase": "^1.0.0",
+        "css-select": "^5.1.0",
+        "css-what": "^6.1.0",
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.3",
+        "domutils": "^3.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/css-select": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
+      "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "boolbase": "^1.0.0",
+        "css-what": "^6.1.0",
+        "domhandler": "^5.0.2",
+        "domutils": "^3.0.1",
+        "nth-check": "^2.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/css-what": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+      "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">= 6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/dom-serializer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+      "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.2",
+        "entities": "^4.2.0"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/domelementtype": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/cheerio-select/node_modules/domhandler": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "domelementtype": "^2.3.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domhandler?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/domutils": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+      "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "dom-serializer": "^2.0.0",
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domutils?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/nth-check": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+      "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "boolbase": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/nth-check?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/dom-serializer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+      "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.2",
+        "entities": "^4.2.0"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/domelementtype": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/cheerio/node_modules/domhandler": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "domelementtype": "^2.3.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domhandler?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/domutils": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+      "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "dom-serializer": "^2.0.0",
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domutils?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/htmlparser2": {
+      "version": "9.1.0",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz",
+      "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==",
+      "funding": [
+        "https://github.com/fb55/htmlparser2?sponsor=1",
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.3",
+        "domutils": "^3.1.0",
+        "entities": "^4.5.0"
+      }
+    },
+    "node_modules/cheerio/node_modules/parse5": {
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+      "license": "MIT",
+      "dependencies": {
+        "entities": "^6.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/parse5/node_modules/entities": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
+      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/cherio": {
+      "version": "1.0.0-rc.2",
+      "resolved": "https://registry.npmjs.org/cherio/-/cherio-1.0.0-rc.2.tgz",
+      "integrity": "sha512-6uMRxujZ6LouVnjv9dYNehbqGEkzQE0anmo70ExdxX3NlyliOcUcAcWDaUEVVPKGGdK5CP6I+bB76+Ud+SEJ6Q==",
+      "license": "MIT",
+      "dependencies": {
+        "css-select": "~1.2.0",
+        "dom-serializer": "~0.1.0",
+        "entities": "~1.1.1",
+        "htmlparser2": "^3.9.1",
+        "lodash": "^4.15.0",
+        "parse5": "^3.0.1"
+      },
+      "engines": {
+        "node": ">= 0.6"
       }
     },
@@ -271,4 +570,16 @@
       }
     },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "license": "MIT",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/concat-map": {
       "version": "0.0.1",
@@ -317,4 +628,25 @@
       }
     },
+    "node_modules/css-select": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "integrity": "sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==",
+      "license": "BSD-like",
+      "dependencies": {
+        "boolbase": "~1.0.0",
+        "css-what": "2.1",
+        "domutils": "1.5.1",
+        "nth-check": "~1.0.1"
+      }
+    },
+    "node_modules/css-what": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+      "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/debug": {
       "version": "4.4.0",
@@ -334,4 +666,13 @@
       }
     },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/depd": {
       "version": "2.0.0",
@@ -341,4 +682,38 @@
       "engines": {
         "node": ">= 0.8"
+      }
+    },
+    "node_modules/dom-serializer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+      "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^1.3.0",
+        "entities": "^1.1.1"
+      }
+    },
+    "node_modules/domelementtype": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/domhandler": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+      "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "domelementtype": "1"
+      }
+    },
+    "node_modules/domutils": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+      "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==",
+      "dependencies": {
+        "dom-serializer": "0",
+        "domelementtype": "1"
       }
     },
@@ -384,4 +759,23 @@
       }
     },
+    "node_modules/encoding-sniffer": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz",
+      "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==",
+      "license": "MIT",
+      "dependencies": {
+        "iconv-lite": "^0.6.3",
+        "whatwg-encoding": "^3.1.1"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
+      }
+    },
+    "node_modules/entities": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+      "license": "BSD-2-Clause"
+    },
     "node_modules/es-define-property": {
       "version": "1.0.1",
@@ -409,4 +803,19 @@
       "dependencies": {
         "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
       },
       "engines": {
@@ -501,4 +910,61 @@
       }
     },
+    "node_modules/follow-redirects": {
+      "version": "1.15.9",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+      "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz",
+      "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
+      "license": "MIT",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/form-data/node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/form-data/node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
     "node_modules/forwarded": {
       "version": "0.2.0",
@@ -524,19 +990,4 @@
       "engines": {
         "node": ">= 0.8"
-      }
-    },
-    "node_modules/fsevents": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
-      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
-      "dev": true,
-      "hasInstallScript": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
       }
     },
@@ -634,4 +1085,19 @@
       }
     },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "license": "MIT",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/hasown": {
       "version": "2.0.2",
@@ -644,4 +1110,18 @@
       "engines": {
         "node": ">= 0.4"
+      }
+    },
+    "node_modules/htmlparser2": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+      "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^1.3.1",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^3.1.1"
       }
     },
@@ -757,4 +1237,10 @@
         "russian-bad-words": "^0.5.0"
       }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+      "license": "MIT"
     },
     "node_modules/math-intrinsics": {
@@ -896,4 +1382,13 @@
       }
     },
+    "node_modules/nth-check": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+      "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "boolbase": "~1.0.0"
+      }
+    },
     "node_modules/object-inspect": {
       "version": "1.13.4",
@@ -950,4 +1445,113 @@
       }
     },
+    "node_modules/parse5": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+      "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
+      "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
+      "license": "MIT",
+      "dependencies": {
+        "domhandler": "^5.0.3",
+        "parse5": "^7.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/domelementtype": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/domhandler": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "domelementtype": "^2.3.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domhandler?sponsor=1"
+      }
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/entities": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
+      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": {
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+      "license": "MIT",
+      "dependencies": {
+        "entities": "^6.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/parse5-parser-stream": {
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
+      "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
+      "license": "MIT",
+      "dependencies": {
+        "parse5": "^7.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/parse5-parser-stream/node_modules/entities": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
+      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/parse5-parser-stream/node_modules/parse5": {
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+      "license": "MIT",
+      "dependencies": {
+        "entities": "^6.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
     "node_modules/parseurl": {
       "version": "1.3.3",
@@ -993,4 +1597,10 @@
         "node": ">= 0.10"
       }
+    },
+    "node_modules/proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+      "license": "MIT"
     },
     "node_modules/pstree.remy": {
@@ -1038,4 +1648,18 @@
       "engines": {
         "node": ">= 0.8"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
       }
     },
@@ -1255,4 +1879,13 @@
       }
     },
+    "node_modules/string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
     "node_modules/supports-color": {
       "version": "5.5.0",
@@ -1327,4 +1960,13 @@
       "license": "MIT"
     },
+    "node_modules/undici": {
+      "version": "6.21.3",
+      "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
+      "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.17"
+      }
+    },
     "node_modules/undici-types": {
       "version": "6.21.0",
@@ -1342,4 +1984,10 @@
       }
     },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+      "license": "MIT"
+    },
     "node_modules/vary": {
       "version": "1.1.2",
@@ -1356,4 +2004,25 @@
       "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
       "license": "BSD-2-Clause"
+    },
+    "node_modules/whatwg-encoding": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+      "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+      "license": "MIT",
+      "dependencies": {
+        "iconv-lite": "0.6.3"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/whatwg-mimetype": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+      "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      }
     },
     "node_modules/whatwg-url": {
Index: backend/package-lock.json
===================================================================
--- backend/package-lock.json	(revision ce371e5a1f811d4ff62f84fbd74dbef9a2b668f3)
+++ backend/package-lock.json	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
@@ -11,5 +11,8 @@
       "dependencies": {
         "@supabase/supabase-js": "^2.39.7",
+        "axios": "^1.9.0",
         "bcrypt": "^6.0.0",
+        "cheerio": "^1.0.0",
+        "cherio": "^1.0.0-rc.2",
         "dotenv": "^16.5.0",
         "express": "^5.1.0",
@@ -144,4 +147,21 @@
       "engines": {
         "node": ">= 8"
+      }
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "license": "MIT"
+    },
+    "node_modules/axios": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
+      "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
+      "license": "MIT",
+      "dependencies": {
+        "follow-redirects": "^1.15.6",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
       }
     },
@@ -200,4 +220,10 @@
       }
     },
+    "node_modules/boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+      "license": "ISC"
+    },
     "node_modules/brace-expansion": {
       "version": "1.1.11",
@@ -260,4 +286,280 @@
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/cheerio": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
+      "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==",
+      "license": "MIT",
+      "dependencies": {
+        "cheerio-select": "^2.1.0",
+        "dom-serializer": "^2.0.0",
+        "domhandler": "^5.0.3",
+        "domutils": "^3.1.0",
+        "encoding-sniffer": "^0.2.0",
+        "htmlparser2": "^9.1.0",
+        "parse5": "^7.1.2",
+        "parse5-htmlparser2-tree-adapter": "^7.0.0",
+        "parse5-parser-stream": "^7.1.2",
+        "undici": "^6.19.5",
+        "whatwg-mimetype": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=18.17"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+      "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "boolbase": "^1.0.0",
+        "css-select": "^5.1.0",
+        "css-what": "^6.1.0",
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.3",
+        "domutils": "^3.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/css-select": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
+      "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "boolbase": "^1.0.0",
+        "css-what": "^6.1.0",
+        "domhandler": "^5.0.2",
+        "domutils": "^3.0.1",
+        "nth-check": "^2.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/css-what": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+      "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">= 6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/fb55"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/dom-serializer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+      "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.2",
+        "entities": "^4.2.0"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/domelementtype": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/cheerio-select/node_modules/domhandler": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "domelementtype": "^2.3.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domhandler?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/domutils": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+      "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "dom-serializer": "^2.0.0",
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domutils?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/cheerio-select/node_modules/nth-check": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+      "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "boolbase": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/nth-check?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/dom-serializer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+      "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.2",
+        "entities": "^4.2.0"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/domelementtype": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/cheerio/node_modules/domhandler": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "domelementtype": "^2.3.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domhandler?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/domutils": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+      "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "dom-serializer": "^2.0.0",
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domutils?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/htmlparser2": {
+      "version": "9.1.0",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz",
+      "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==",
+      "funding": [
+        "https://github.com/fb55/htmlparser2?sponsor=1",
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.3",
+        "domutils": "^3.1.0",
+        "entities": "^4.5.0"
+      }
+    },
+    "node_modules/cheerio/node_modules/parse5": {
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+      "license": "MIT",
+      "dependencies": {
+        "entities": "^6.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/cheerio/node_modules/parse5/node_modules/entities": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
+      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/cherio": {
+      "version": "1.0.0-rc.2",
+      "resolved": "https://registry.npmjs.org/cherio/-/cherio-1.0.0-rc.2.tgz",
+      "integrity": "sha512-6uMRxujZ6LouVnjv9dYNehbqGEkzQE0anmo70ExdxX3NlyliOcUcAcWDaUEVVPKGGdK5CP6I+bB76+Ud+SEJ6Q==",
+      "license": "MIT",
+      "dependencies": {
+        "css-select": "~1.2.0",
+        "dom-serializer": "~0.1.0",
+        "entities": "~1.1.1",
+        "htmlparser2": "^3.9.1",
+        "lodash": "^4.15.0",
+        "parse5": "^3.0.1"
+      },
+      "engines": {
+        "node": ">= 0.6"
       }
     },
@@ -287,4 +589,16 @@
       }
     },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "license": "MIT",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/concat-map": {
       "version": "0.0.1",
@@ -333,4 +647,25 @@
       }
     },
+    "node_modules/css-select": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "integrity": "sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==",
+      "license": "BSD-like",
+      "dependencies": {
+        "boolbase": "~1.0.0",
+        "css-what": "2.1",
+        "domutils": "1.5.1",
+        "nth-check": "~1.0.1"
+      }
+    },
+    "node_modules/css-what": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+      "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/debug": {
       "version": "4.4.0",
@@ -350,4 +685,13 @@
       }
     },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/depd": {
       "version": "2.0.0",
@@ -357,4 +701,38 @@
       "engines": {
         "node": ">= 0.8"
+      }
+    },
+    "node_modules/dom-serializer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+      "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^1.3.0",
+        "entities": "^1.1.1"
+      }
+    },
+    "node_modules/domelementtype": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/domhandler": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+      "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "domelementtype": "1"
+      }
+    },
+    "node_modules/domutils": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+      "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==",
+      "dependencies": {
+        "dom-serializer": "0",
+        "domelementtype": "1"
       }
     },
@@ -400,4 +778,23 @@
       }
     },
+    "node_modules/encoding-sniffer": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz",
+      "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==",
+      "license": "MIT",
+      "dependencies": {
+        "iconv-lite": "^0.6.3",
+        "whatwg-encoding": "^3.1.1"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
+      }
+    },
+    "node_modules/entities": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+      "license": "BSD-2-Clause"
+    },
     "node_modules/es-define-property": {
       "version": "1.0.1",
@@ -425,4 +822,19 @@
       "dependencies": {
         "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
       },
       "engines": {
@@ -517,4 +929,61 @@
       }
     },
+    "node_modules/follow-redirects": {
+      "version": "1.15.9",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+      "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz",
+      "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
+      "license": "MIT",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/form-data/node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/form-data/node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
     "node_modules/forwarded": {
       "version": "0.2.0",
@@ -650,4 +1119,19 @@
       }
     },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "license": "MIT",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/hasown": {
       "version": "2.0.2",
@@ -660,4 +1144,18 @@
       "engines": {
         "node": ">= 0.4"
+      }
+    },
+    "node_modules/htmlparser2": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+      "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+      "license": "MIT",
+      "dependencies": {
+        "domelementtype": "^1.3.1",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^3.1.1"
       }
     },
@@ -773,4 +1271,10 @@
         "russian-bad-words": "^0.5.0"
       }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+      "license": "MIT"
     },
     "node_modules/math-intrinsics": {
@@ -912,4 +1416,13 @@
       }
     },
+    "node_modules/nth-check": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+      "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "boolbase": "~1.0.0"
+      }
+    },
     "node_modules/object-inspect": {
       "version": "1.13.4",
@@ -966,4 +1479,113 @@
       }
     },
+    "node_modules/parse5": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+      "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
+      "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
+      "license": "MIT",
+      "dependencies": {
+        "domhandler": "^5.0.3",
+        "parse5": "^7.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/domelementtype": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/domhandler": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "domelementtype": "^2.3.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domhandler?sponsor=1"
+      }
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/entities": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
+      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": {
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+      "license": "MIT",
+      "dependencies": {
+        "entities": "^6.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/parse5-parser-stream": {
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
+      "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
+      "license": "MIT",
+      "dependencies": {
+        "parse5": "^7.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/parse5-parser-stream/node_modules/entities": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
+      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/parse5-parser-stream/node_modules/parse5": {
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+      "license": "MIT",
+      "dependencies": {
+        "entities": "^6.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
     "node_modules/parseurl": {
       "version": "1.3.3",
@@ -1009,4 +1631,10 @@
         "node": ">= 0.10"
       }
+    },
+    "node_modules/proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+      "license": "MIT"
     },
     "node_modules/pstree.remy": {
@@ -1054,4 +1682,18 @@
       "engines": {
         "node": ">= 0.8"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
       }
     },
@@ -1271,4 +1913,13 @@
       }
     },
+    "node_modules/string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
     "node_modules/supports-color": {
       "version": "5.5.0",
@@ -1343,4 +1994,13 @@
       "license": "MIT"
     },
+    "node_modules/undici": {
+      "version": "6.21.3",
+      "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
+      "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.17"
+      }
+    },
     "node_modules/undici-types": {
       "version": "6.21.0",
@@ -1358,4 +2018,10 @@
       }
     },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+      "license": "MIT"
+    },
     "node_modules/vary": {
       "version": "1.1.2",
@@ -1372,4 +2038,25 @@
       "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
       "license": "BSD-2-Clause"
+    },
+    "node_modules/whatwg-encoding": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+      "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+      "license": "MIT",
+      "dependencies": {
+        "iconv-lite": "0.6.3"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/whatwg-mimetype": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+      "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      }
     },
     "node_modules/whatwg-url": {
Index: backend/package.json
===================================================================
--- backend/package.json	(revision ce371e5a1f811d4ff62f84fbd74dbef9a2b668f3)
+++ backend/package.json	(revision ce1bb4529de44fc291d59d7bf2171d2a74476235)
@@ -14,5 +14,8 @@
   "dependencies": {
     "@supabase/supabase-js": "^2.39.7",
+    "axios": "^1.9.0",
     "bcrypt": "^6.0.0",
+    "cheerio": "^1.0.0",
+    "cherio": "^1.0.0-rc.2",
     "dotenv": "^16.5.0",
     "express": "^5.1.0",
Index: ckend/scripts/deleteAllUsers.js
===================================================================
--- backend/scripts/deleteAllUsers.js	(revision ce371e5a1f811d4ff62f84fbd74dbef9a2b668f3)
+++ 	(revision )
@@ -1,43 +1,0 @@
-const supabase = require('../supabaseClient');
-
-async function deleteAllUsers() {
-  // 1. Get all user IDs from the users table
-  const { data: users, error: fetchError } = await supabase
-    .from('users')
-    .select('id');
-  if (fetchError) {
-    console.error('Error fetching users:', fetchError);
-    return;
-  }
-
-  if (!users || users.length === 0) {
-    console.log('No users found.');
-    return;
-  }
-
-  // 2. Delete users from Supabase Auth
-  for (const user of users) {
-    const { error: authError } = await supabase.auth.admin.deleteUser(user.id);
-    if (authError) {
-      if (authError.status === 404 && authError.code === 'user_not_found') {
-        console.warn(`Auth user ${user.id} not found (already deleted).`);
-      } else {
-        console.error(`Error deleting auth user ${user.id}:`, authError);
-      }
-    } else {
-      console.log(`Deleted auth user ${user.id}`);
-    }
-  }
-  // 3. Delete all users from the users table
-  const { error: tableError } = await supabase
-    .from('users')
-    .delete()
-    .not('id', 'is', null);
-  if (tableError) {
-    console.error('Error deleting users from table:', tableError);
-  } else {
-    console.log('Deleted all users from users table.');
-  }
-}
-
-deleteAllUsers();
