Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules
.DS_Store
npm-debug.log
TODO.md
58 changes: 58 additions & 0 deletions exercises/async_loops/exercise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"use strict"

var deepEqual = require('deep-eql')
var inspect = require('util').inspect
var loremIpsum = require('lorem-ipsum')
var random = require('../randomizer')
var runner = require('../runner')

// All deepEqual impls (assert, deep-eql…) seem to b0rk when multiple objects
// in an array share the same `id` value (wtf?!), so we make sure they're unique.
var userCount = random.int(10, 20)
var userIds = []
while (userIds.length < userCount) {
var id = random.int(0, 1000)
if (-1 !== userIds.indexOf(id)) continue
userIds.push(id)
}

var users = random.arrayOf(userCount, function() {
return {
id: userIds.shift(),
name: random.words(2, { capitalized: true })
}
})

var fx

module.exports = runner.custom(function(f) {
fx = f
}).wrapUp(function(callback) {
var self = this
var ids = users.map(function(user) {return user.id })
var load = function(id, fn) {
setTimeout(function() {
var match = users.filter(function(user) {return user.id === id})
if (match.length) fn(match[0])
else fn(null)
}, random.int(0, 1000))
}
var done = function(submittedUsers) {
clearTimeout(tooLong)
console.log(submittedUsers)

if (!deepEqual(submittedUsers, users)) {
self.emit('fail', self.__('bad_result', inspect(users), inspect(submittedUsers)))
return callback(null, false)
}

console.log(self.__('all_loaded', submittedUsers.length))
callback(null, true)
}

fx.call(fx, ids, load, done)
var tooLong = setTimeout(function() {
self.emit('fail', self.__('took_too_long'))
callback(null, false)
}, 1000)
}).quiet(users)
51 changes: 51 additions & 0 deletions exercises/async_loops/problem.fr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
Le code ci-dessous est cassé !

Un développeur Java a ajouté le code atroce ci-dessous à notre projet et ne l’a pas testé !

```js
function loadUsers(userIds, load, done) {
var users = []
for (var i = 0; i < userIds.length; i++) {
users.push(load(userIds[i]))
}
return users
}

module.exports = loadUsers
```

## Défi

Corrigez ce code ! La fonction de rappel `done()` devrait être appelée une fois que tous les utilisateurs ont été chargés. L’ordre des utilisateurs doit correspondre à celui des IDs reçus. Vu que cette fonction est asynchrone, on se fiche de sa valeur de retour.

## Arguments

* `userIds` : un tableau d’IDs numériques d’utilisateurs.
* `load` : une fonction asynchrone de chargement d’un objet utilisateur. Reçoit un ID et une fonction de rappel. Celle-ci sera appelée avec le résultat du chargement pour l’utilisateur avec l’ID indiqué (soit un objet utilisateur, soit `null`).
* `done` : une fonction de rappel finale, qui attend comme argument un tableau des objets utilisateurs chargés.

## Conditions

* N’utilisez pas de boucles `for`/`while` (mais `Array#forEach()` reste autorisé).
* L’ordre des utilisateurs dans le tableau passé à `done()` doit correspondre à celui des IDs dans le tableau `userIds` que vous aurez reçu.
* Les utilisateurs doivent être chargés en parallèle, donc la séquence entière ne devrait pas dépasser une seconde.
* Ne créez aucune fonction superflue

## Conseils

* Vous n’avez pas besoin d’un tri pour maintenir l’ordre du résultat.
* Si vous utilisez `console.log()`, ça va impacter notre vérification. Ne vous en servez que pendant votre phase de mise au point avec `{appname} run`.

## Base de travail

```js
function loadUsers(userIds, load, done) {
var users = []
for (var i = 0; i < userIds.length; i++) {
users.push(load(userIds[i]))
}
return users
}

module.exports = loadUsers
```
File renamed without changes.
19 changes: 6 additions & 13 deletions problems/basic_call/setup.js → exercises/basic_call/exercise.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
"use strict"

var input = require('../../input')
var random = require('../randomizer')
var runner = require('../runner')

function randomInt(min, max) {
return Math.floor((Math.random() * (max - min + 1)) + min)
}
var input = random.arrayOfInts(20, 0, 10)

module.exports = input(new Array(randomInt(0, 20))
.join(',')
.split(',')
.map(function() {
return randomInt(0, 10)
})).wrap(function(input, mod) {
var numbers = input[0]
var exercise = module.exports = runner.custom(function(fx, numbers) {
var valid = 1
var objects = [{quack: true}].concat(numbers.map(function(num) {
switch(num) {
Expand Down Expand Up @@ -60,5 +53,5 @@ module.exports = input(new Array(randomInt(0, 20))
}
}))

console.log('Matched %d of %d valid objects from %d total.', mod.apply(mod, objects), valid, objects.length)
})
return exercise.__('matched_objects', fx.apply(null, objects), valid, objects.length)
}).hideInput(input)
104 changes: 104 additions & 0 deletions exercises/basic_call/problem.fr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
JavaScript supporte le « duck typing », une méthode dynamique de test des types d’objet. Elle repose sur l’analyse des méthodes et propriétés d’un objet pour déterminer sa sémantique, plutôt que de se fier à un héritage de classe particulière ou à l’implémentation d’une interface abstraite… Le nom de ce concept vient du « test du canard », attribué à James Whitcomb Riley, qu’on peut formuler ainsi :

> « Quand je vois un volatile qui marche comme un canard, nage comme un canard, et cancane comme un canard, alors j’appelle ce volatile un canard. »

En JavaScript, pour écrire des programmes robustes, nous avons parfois besoin de vérifier qu’un objet est conforme au type dont nous avons besoin.

Nous pouvons utiliser `Object#hasOwnProperty()` pour détecter qu’un objet « a » une propriété définie sur lui-même, ce qu’on appelle une *propriété propre* (par opposition à une propriété hérité du prototype) :

```js
var duck = {
quack: function() {
console.log('quack')
}
}

duck.hasOwnProperty('quack') // => true
```

Nous n’avons toutefois pas équipé `duck` d’une méthode `hasOwnProperty()`, alors d’où vient-elle ?

`duck` a été créé avec la syntaxe littérale `{…}`, qui définit un objet, de sorte qu’il hérite automatiquement de `Object.prototype` :

```js
var object = {quack: true}

Object.getPrototypeOf(object) === Object.prototype // => true
object.hasOwnProperty('quack') // => true
```

Mais qu’en serait-il pour un objet qui n’hérite pas de `Object.prototype` ?

```js
// Créons un objet avec un prototype `null`
var object = Object.create(null)
object.quack = function() {
console.log('quack')
}

Object.getPrototypeOf(object) === Object.prototype // => false
Object.getPrototypeOf(object) === null // => true

object.hasOwnProperty('quack')
// => TypeError: Object object has no method 'hasOwnProperty'
```

Nous pouvons toujours appeler la `hasOwnProperty()` de `Object.prototype`, ceci dit, du moment que nous l’appelons avec un `this` qui « ressemble à un objet ». `Function#call` nous permet d’appeler n’importe quelle fonction avec un `this` que nous contrôlons.

```js
// Le premier argument de `call` sera le `this`
// Le reste des arguments est passé à la fonction

Object.prototype.hasOwnProperty.call(object, 'quack') // => true
```

# Défi

Écrivez une fonction `duckCount()` qui inspecte les arguments qu’on lui passe et renvoie le nombre de ceux qui ont une propriété propre `quack` définie. Ignorez les propriétés hérités des prototypes.

Exemple :

```js
var notDuck = Object.create({quack: true})
var duck = {quack: true}
duckCount(duck, notDuck) // 1
```
## Arguments

Vous recevrez un nombre variable d’arguments, d’un appel à l’autre. Chaque argument pourra être d’un type quelconque, avec des propriétés quelconques. Certains arguments auront une propriété `quack`, parfois héritée du prototype. Certains pourrons ne pas être équipés de `hasOwnProperty()`.

## Conditions

* N’utilisez ni boucle (`for`, `while`…) ni `Array.prototype.forEach`
* Ne maintenez pas de variable pour le compteur / l’accumulateur.
* Ne créez aucune fonction superflue

## Conseil

La variable automatique `arguments`, disponible dans toute fonction, est un *objet* qui ressemble à un tableau sans en être vraiment un :

```js
{
0: 'argument0',
1: 'argument1', // etc.
length: 2
}
```

## Ressources

* https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Function/call
* https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/hasOwnProperty
* https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/L_op%C3%A9rateur_in
* https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/slice#Array-like
* https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Fonctions/arguments

## Base de travail

```js
function duckCount() {
// VOTRE SOLUTION ICI
}

module.exports = duckCount
```
File renamed without changes.
39 changes: 39 additions & 0 deletions exercises/basic_every_some/exercise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"use strict"

var random = require('../randomizer')
var runner = require('../runner')

function makeUser() {
return {
id: random.int(0, 1000),
name: random.words(2, { capitalized: true })
}
}

function makeListOfUsers() {
return random.arrayOf(10, 100, makeUser)
}

var good = makeListOfUsers()
var bad = makeListOfUsers()
var lists = random.arrayOf(20, function() {
return random.arrayOf(20, function() {
if (Math.random() < 0.95) {
return good[random.int(0, 10)]
} else {
return bad[random.int(0, 10)]
}
})
})

var exercise = module.exports = runner.custom(function(fx, good, lists) {
var test = fx(good)

var goodLists = 0

lists.forEach(function(list) {
test(list) && ++goodLists
})

return exercise.__('found_good_lists', goodLists)
}).hideInput(good, lists)
59 changes: 59 additions & 0 deletions exercises/basic_every_some/problem.fr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Défi

Écrivez une fonction qui reçoit une liste d’utilisateurs valides, et renvoie une fonction qui, elle, retournera `true` si tous les utilisateurs qu’on lui passe sont dans la liste originellement fournie.

Vous n’aurez qu’à examiner la correspondance des propriétés `id`.

## Exemple

```js
var goodUsers = [
{ id: 1 },
{ id: 2 },
{ id: 3 }
]

// `checkUsersValid` est la fonction que vous allez écrire
var testAllValid = checkUsersValid(goodUsers)

testAllValid([
{ id: 2 },
{ id: 1 }
])
// => true

testAllValid([
{ id: 2 },
{ id: 4 },
{ id: 1 }
])
// => false
```

## Arguments

* `goodUsers` : une liste d’utilisateurs valides

Utilisez `Array#some()` et `Array#every()` pour vérifier que chaque utilisateur passé à la fonction que vous aurez générée existe dans le tableau initialement transmis à la fonction exportée.

## Conditions

* N’utilisez ni boucle (`for`, `while`…) ni `Array.prototype.forEach`
* Ne créez aucune fonction superflue

## Ressources

* https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/every
* https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/some

## Base de travail

```js
function checkUsersValid(goodUsers) {
return function allUsersValid(submittedUsers) {
// VOTRE SOLUTION ICI
};
}

module.exports = checkUsersValid
```
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Use array#some and Array#every to check every user passed to your returned funct

```js
function checkUsersValid(goodUsers) {
return function(submittedUsers) {
return function allUsersValid(submittedUsers) {
// SOLUTION GOES HERE
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = function checkUsersValid(goodUsers) {
return function(submittedUsers) {
return function allUsersValid(submittedUsers) {
return submittedUsers.every(function(submittedUser) {
return goodUsers.some(function(goodUser) {
return goodUser.id === submittedUser.id
Expand Down
11 changes: 11 additions & 0 deletions exercises/basic_filter/exercise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use strict"

var loremIpsum = require('lorem-ipsum')
var random = require('../randomizer')
var runner = require('../runner')

var input = random.arrayOf(10, 30, function() {
return { message: loremIpsum() }
})

module.exports = runner.hideInput(input)
Loading