Category: Développement

Kronotop : Une base de données de documents distribuée et transactionnelle compatible avec Redis

2025-01-20
Kronotop : Une base de données de documents distribuée et transactionnelle compatible avec Redis

Kronotop est une base de données de documents distribuée et transactionnelle compatible avec Redis, utilisant FoundationDB. Elle supporte un langage de requête de type MQL, les transactions ACID et un moteur de stockage sur disque avec un modèle de réplication principal-secondaire. Encore en développement précoce avec une API instable, elle possède déjà des fonctionnalités telles que ZMap (un stockage clé-valeur ordonné), des espaces de noms et un support partiel pour les structures de données Redis (chaînes et hachages). Les plans futurs incluent la prise en charge d'autres structures de données Redis (listes, ensembles, ensembles ordonnés) et une structure de données Bucket pour stocker des documents de type JSON avec prise en charge du langage de requête MQL et des transactions.

Développement

Proposition : Effets essentiels pour C

2025-01-20

Cette proposition suggère d’améliorer le système de types principal de C avec un système de type et d’effet, exigeant que les fonctions et les blocs déclarent les effets de leur évaluation. Cela améliore la composition de la métaprogrammation et simplifie la définition des restrictions de type MISRA. Le système suit et vérifie les effets, mais ne gère pas le traitement des effets dynamiques. Trois groupes principaux d’effets sont proposés : locaux (par exemple, écriture locale), persistants (par exemple, écriture non locale) et contrôle (par exemple, transfert de contrôle non local). La vérification statique des effets est obtenue en attribuant un type et un effet à chaque instruction, expression et corps de fonction, en rejetant les effets locaux pour garantir un ordre correct. De bonnes pratiques sont suggérées, telles que la limitation de l’ampleur des effets `mut` et `vol` et la spécification de vérifications d’effets pour les opérateurs et les structures de contrôle. L’objectif est d’améliorer la sécurité, la lisibilité et la composition de C, en particulier pour la métaprogrammation et la gestion des ressources.

Développement système de types

SRCL : Une bibliothèque de composants React à l'esthétique terminal

2025-01-20
SRCL : Une bibliothèque de composants React à l'esthétique terminal

SRCL est un référentiel de composants et de styles React open source qui vous aide à construire des applications web, des applications de bureau et des sites web statiques avec une esthétique de terminal. Il dispose d'une collection complète de composants, notamment des barres d'action, des accordéons, des boutons, des bannières d'alerte, des avatars, des badges, des chargeurs, des articles de blog, des breadcrumbs, des cartes, des cases à cocher, des échiquiers, des blocs de code, des boîtes combinées, des tableaux de données, des sélecteurs de date, des tableaux de bord, des exemples de bases de données, des menus déroulants, des états vides, des champs de saisie, des formulaires, des liens, des listes, des messages, des modales, des barres de navigation, des popovers, des barres de progression, des boutons radio, des sélecteurs, des barres latérales, des curseurs, des tableaux, des zones de texte, des info-bulles et des vues d'arborescence, le tout stylisé avec un aspect rétro de terminal.

WordPecker : App d'apprentissage des langues personnalisée avec des leçons de type Duolingo et un vocabulaire personnalisé

2025-01-20
WordPecker : App d'apprentissage des langues personnalisée avec des leçons de type Duolingo et un vocabulaire personnalisé

WordPecker est une application d'apprentissage des langues personnalisée qui combine des leçons de type Duolingo avec vos propres listes de vocabulaire. Ajoutez facilement des mots provenant de livres, d'articles ou de vidéos, et révisez-les grâce à des quiz interactifs et des leçons générées par un modèle de langage de grande taille (LLM). L'application s'attaque aux points faibles de l'acquisition du vocabulaire dans l'apprentissage traditionnel des langues en connectant l'apprentissage au contexte, ce qui améliore l'efficacité et la rétention. Actuellement dotée de plusieurs types de questions, les développements futurs incluent le suivi des progrès, le partage des listes, et plus encore.

Développement

Tolérance à la frustration : la clé pour survivre dans les grandes organisations

2025-01-20
Tolérance à la frustration : la clé pour survivre dans les grandes organisations

Dans les grandes organisations, les ambitions se heurtent souvent à la réalité. Cet article explore la « tolérance à la frustration », un facteur crucial qui détermine le succès dans la navigation des complexités organisationnelles, des conflits et des progrès lents. Une forte tolérance à la frustration permet aux individus de considérer les défis comme gérables, tandis qu'une faible tolérance conduit à l'abandon, à la négativité et à l'épuisement professionnel. Quatre causes principales de la faible tolérance à la frustration sont identifiées : les exigences de confort, de justice, de réussite et de maîtrise émotionnelle. Remettre en question les frictions organisationnelles comme un catalyseur d'innovation permet de développer une plus grande tolérance à la frustration et de prospérer dans des environnements complexes.

La Magie Mathématique Derrière les Problèmes de Divisibilité en Licence

2025-01-20
La Magie Mathématique Derrière les Problèmes de Divisibilité en Licence

Cet article de blog explore l'origine des problèmes courants dans les cours de mathématiques de licence, tels que la démonstration qu'un polynôme est toujours un multiple d'un certain entier. L'auteur souligne que ces problèmes proviennent du dénombrement combinatoire, plus précisément du dénombrement de Pólya-Redfield. Cette méthode utilise la formule de dénombrement des orbites sous l'action d'un groupe pour relier la valeur d'un polynôme au dénombrement d'une certaine structure combinatoire, garantissant que le polynôme est toujours un multiple d'un entier spécifique. L'article utilise deux exemples, le dénombrement de bracelets et le dénombrement de grilles de morpion, pour expliquer comment le dénombrement de Pólya-Redfield est utilisé pour construire ces problèmes. Il propose également une conjecture sur le fait que tous ces polynômes proviennent du dénombrement de Pólya-Redfield.

Systemd : La prise de contrôle furtive de l’écosystème Linux par Red Hat ?

2025-01-20

Cet article explore les véritables motivations derrière systemd, révélant comment Red Hat a tiré parti de ses intérêts commerciaux dans les dispositifs embarqués pour transformer systemd d’un simple système init en un composant central du système d’exploitation Linux. L’auteur affirme que Red Hat a utilisé diverses tactiques, notamment en faisant pression sur des projets open source pour qu’ils dépendent de systemd et en recrutant des développeurs d’autres distributions, pour exercer un contrôle sur l’écosystème Linux, provoquant une réaction négative au sein de la communauté open source et menant à la démission de plusieurs développeurs Debian. Systemd est décrit comme un système monolithique soulevant des préoccupations en matière de confidentialité, et l’ambition de Red Hat est présentée comme celle de créer le prochain Windows. L’article conclut en plaidant pour un retour au développement communautaire et en recommandant des alternatives à systemd, telles que runit et s6.

Développement

Parinfer : une façon plus simple d'éditer Lisp

2025-01-20

Parinfer est un mode d'édition innovant pour les langages de programmation Lisp qui simplifie la programmation Lisp en reliant intelligemment les parenthèses et l'indentation. Il s'attaque au problème notoire des parenthèses en Lisp, offrant une expérience d'édition plus intuitive aux débutants et aux experts. Parinfer possède deux modes : le mode Indentation et le mode Parenthèses, permettant aux utilisateurs de se concentrer sur l'indentation ou les parenthèses tandis que Parinfer gère automatiquement l'autre. Il fournit également des fonctionnalités similaires à Paredit sans nécessiter de raccourcis clavier complexes. Au cœur de Parinfer, on trouve une définition formelle de la relation entre les parenthèses et l'indentation, et un mécanisme d'ajustement automatique intelligent basé sur cette définition.

Développement Éditeur

Démos communautaires CFRS[] : Dessiner de l’art incroyable avec six commandes

2025-01-20

CFRS[] est un langage de dessin extrêmement minimaliste composé de seulement six commandes (C, F, R, S, [, ]). Ce document rassemble des démos CFRS[] contribuées par les membres de la communauté, y compris des démos dynamiques (utilisant la commande 'S' pour l'animation) et des démos statiques. Ces démos présentent une grande variété de formes, telles que des fleurs, des croix, des kaléidoscopes et des feuilles, démontrant la puissance expressive du langage. Même des commandes simples peuvent créer de l’art époustouflant. Cette collection offre du plaisir et de l’inspiration aux débutants et aux passionnés de programmation.

Enums TypeScript : cas d'utilisation et alternatives

2025-01-20

Cet article de blog examine de plus près les énumérations TypeScript : comment fonctionnent-elles ? Quels sont leurs cas d’utilisation ? Quelles sont les alternatives si nous ne voulons pas les utiliser ? L’article se conclut par des recommandations sur quand utiliser quelle approche. Il couvre les bases des énumérations, les cas d’utilisation (par exemple, espace de noms pour les constantes avec des valeurs primitives, type personnalisé avec des valeurs uniques, espace de noms pour les constantes avec des valeurs d’objet), les alternatives (par exemple, littéraux d’objet, union de types littéraux de chaîne) et comment effectuer des vérifications d’exhaustivité et énumérer les membres.

Développement

Linux 6.13 Stable Sortie : Optimisations AMD, Support Apple Élargi et Plus

2025-01-20

Le noyau stable Linux 6.13 est arrivé, apportant des fonctionnalités intéressantes telles que des optimisations AMD 3D V-Cache pour les processeurs Ryzen X3D, une meilleure efficacité énergétique pour les serveurs AMD EPYC 9005 "Turin", la prise en charge de plus anciens appareils Apple et des optimisations de compilateur AutoFDO/Propeller. Un support initial pour les graphiques Intel Xe3, la prise en charge de NVMe 2.1 et une infrastructure de langage Rust étendue sont également inclus. Marquant la première version majeure du noyau de 2025, Linux 6.13 améliore considérablement les performances et la compatibilité matérielle.

Développement

GitHub Actions : Pourquoi j'y réfléchis à deux fois

2025-01-20

Cet article détaille les frustrations liées à l'utilisation de GitHub Actions pour le CI/CD dans un grand monorepo avec 15 ingénieurs poussant constamment du code vers la branche principale. L'auteur souligne des problèmes clés : des vérifications obligatoires défectueuses pour les pull requests dans une configuration monorepo, une faible réutilisabilité du workflow et une gestion YAML difficile, l'absence d'environnement de développement local et l'attitude peu réactive de GitHub face aux retours utilisateurs. La conclusion préconise d'explorer des plateformes CI/CD alternatives comme GitLab, Jenkins ou même Dagger pour de meilleures solutions.

Développement

Fournisseur Terraform pour les commutateurs HRUI : Simplification de la configuration du réseau

2025-01-20
Fournisseur Terraform pour les commutateurs HRUI : Simplification de la configuration du réseau

Le projet open-source `terraform-provider-hrui` fournit un fournisseur Terraform pour gérer les commutateurs de la marque HRUI (Horaco, Sodola, XikeStor, etc.). Il utilise la bibliothèque goquery pour interagir avec l'interface web du commutateur et a été testé avec succès sur le Horaco ZX-SWTG124AS. Les contributions sont les bienvenues, et le projet est sous licence MPL-2.0.

Développement Gestion de réseau

Révolutionner l'autorisation à grain fin : le moteur de calcul incrémental de Feldera

2025-01-20
Révolutionner l'autorisation à grain fin : le moteur de calcul incrémental de Feldera

Feldera présente une approche révolutionnaire de l'autorisation à grain fin (FGA). Les systèmes FGA traditionnels évaluent les demandes d'autorisation en temps réel, ce qui entraîne une inefficacité. Feldera précalcule toutes les décisions d'autorisation et utilise son moteur de calcul incrémental (basé sur SQL) pour mettre à jour les résultats, transformant les demandes d'autorisation en simples recherches clé-valeur. Même avec de grands graphes d'objets, Feldera traite les modifications en quelques millisecondes, améliorant considérablement les performances. L'article détaille les principes de la FGA et montre comment construire un moteur FGA haute performance à l'aide de SQL, démontrant sa supériorité dans la gestion de grands ensembles de données.

Rhai : Un langage de script embarqué sûr et efficace pour Rust

2025-01-20
Rhai : Un langage de script embarqué sûr et efficace pour Rust

Rhai est un langage de script et un moteur d'évaluation embarqués pour Rust, offrant un moyen sûr et facile d'ajouter des fonctionnalités de script à n'importe quelle application. Il cible toutes les architectures CPU et OS prises en charge par Rust, y compris WebAssembly, et possède une syntaxe simple, similaire à JavaScript. Rhai se distingue par son évaluation efficace et son intégration étroite avec les fonctions et les types natifs de Rust, permettant le passage et l'utilisation transparents des valeurs Rust. Ses robustes fonctionnalités de sécurité le protègent contre les attaques malveillantes telles que les dépassements de pile et les scripts incontrôlés.

Développement Langage de script Embarqué

Géométrie computationnelle avec des primitives probabilistiquement bruitées

2025-01-20

Une nouvelle prépublication explore les algorithmes de géométrie computationnelle sous des opérations primitives probabilistiquement bruitées. De nombreux algorithmes de ce type reposent sur des primitives accédant aux coordonnées d'entrée et les convertissant en informations combinatoires. L'article considère des primitives produisant aléatoirement des résultats incorrects et étudie comment obtenir des résultats corrects avec une forte probabilité sans perte d'efficacité significative. Il s'avère que pour certains problèmes (comme la construction de l'enveloppe convexe), le ralentissement dû à la répétition peut être évité, tandis que pour d'autres (comme la recherche des paires de points les plus proches), ce n'est pas possible. Cela fait le lien avec des travaux antérieurs sur la complexité de la communication utilisant des comparaisons bruitées pour améliorer l'efficacité.

Les Deux Choses les Plus Difficiles en Informatique

2025-01-20
Les Deux Choses les Plus Difficiles en Informatique

Une blague classique chez les programmeurs dit : "Il n'y a que deux choses difficiles en informatique : l'invalidation du cache et la nomination des choses." Cet article retrace l'origine et l'évolution de cette phrase spirituelle, explorant son humour et sa signification plus profonde. De sa forme concise initiale à des variations intégrant des 'erreurs d'indice hors limites' et plus encore, la blague reflète les nombreux défis que les programmeurs rencontrent quotidiennement, soulignant la complexité et le divertissement inhérents à la programmation.

Développement

Comment les interruptions impactent les ingénieurs logiciels : une étude approfondie

2025-01-20
Comment les interruptions impactent les ingénieurs logiciels : une étude approfondie

Une nouvelle recherche explore comment les interruptions affectent la productivité et le stress des ingénieurs logiciels. L’étude a révélé que différents types d’interruptions (par exemple, les notifications en personne par rapport aux notifications à l’écran) ont un impact différent sur la programmation, la compréhension du code et la revue de code, les tâches complexes étant moins affectées. Fait intéressant, les données physiologiques (variabilité de la fréquence cardiaque) ont montré moins de stress avec les interruptions en personne, mais les ingénieurs les ont perçues comme plus stressantes. Les responsables doivent donc prioriser le stress perçu par les ingénieurs, en minimisant les interruptions de haute priorité et en fournissant du temps de concentration pour des tâches telles que la programmation afin d’améliorer l’efficacité de l’équipe.

Développement

La vérité dérangeante sur l'indentation Lisp

2025-01-19

Les programmeurs Lisp débattent depuis longtemps du meilleur style d'indentation. Cet article explore différentes approches, notamment l'absence d'indentation, l'indentation alignée sur les fonctions, l'indentation de remplissage d'espace et l'indentation de macro "malade" controversée de l'auteur. L'indentation alignée sur les fonctions devient difficile à gérer avec un imbriquement profond, tandis que l'indentation de remplissage d'espace, bien qu'efficace, est insuffisante dans les cas extrêmes. L'auteur préconise un style de macro "malade", qui, malgré son caractère non conventionnel, préserve la lisibilité dans le code profondément imbriqué et fonctionne bien avec la plupart des outils d'indentation. Les lecteurs sont invités à partager leurs styles préférés.

Développement style de codage

Autocorrection Git : Trop rapide même pour les pilotes de F1 ?

2025-01-19
Autocorrection Git : Trop rapide même pour les pilotes de F1 ?

La fonction d'autocorrection de Git, avec son temps de réponse de 0,1 seconde, a suscité des débats. Cet article explore sa conception et sa vitesse étonnamment rapide. Ce n'est pas le comportement par défaut ; il est configurable via le paramètre `help.autocorrect`. Initialement, un temps d'attente court et humoristique a été défini, puis amélioré pour permettre des délais définis par l'utilisateur ou des invites de confirmation. L'auteur analyse également l'algorithme d'autocorrection de Git et suggère des améliorations pour une meilleure expérience utilisateur.

Développement autocorrection

Construisez une minuscule autorité de certification sécurisée par YubiKey pour votre homelab

2025-01-19
Construisez une minuscule autorité de certification sécurisée par YubiKey pour votre homelab

Ce tutoriel vous guide dans la construction d'une autorité de certification (CA) sécurisée et protégée par YubiKey sur un Raspberry Pi. En utilisant le logiciel open source step-ca et un générateur de nombres aléatoires Infinite Noise TRNG en option pour une meilleure aléatoire, vous créerez un mini-serveur ACME interne pour les besoins TLS de votre homelab. Le guide couvre la configuration du système, la création de PKI, la configuration de la CA, l'ajout d'un provisionneur ACME et l'implémentation de services systemd pour gérer le retrait/l'insertion de la YubiKey. Le résultat ? Une CA minuscule, sécurisée et sans SSH.

La lutte surprenante pour obtenir une heure d'époque UNIX à partir d'une chaîne UTC en C ou C++

2025-01-19
La lutte surprenante pour obtenir une heure d'époque UNIX à partir d'une chaîne UTC en C ou C++

Cet article explore les complexités de la conversion de chaînes de caractères UTC en horodatages Unix en C/C++. L'auteur découvre des comportements inattendus dans les fonctions de gestion du temps POSIX dans diverses bibliothèques et langages C. L'accent est mis sur l'utilisation des fonctions `strptime()`, `mktime()` et `timegm()`, en soulignant les problèmes liés à l'heure d'été et aux paramètres régionaux. Des solutions sont proposées, notamment l'utilisation de `timegm()` pour les heures UTC et l'exploitation des flux C++ pour contourner les problèmes de paramètres régionaux. L'article conclut en recommandant des bibliothèques de gestion du temps plus robustes disponibles en C++20 et versions ultérieures, telles que la bibliothèque tz de Howard Hinnant.

Développement

Cours Essentiel de Robotique et ROS 2 Open Source : Apprenez ROS 2 à partir de zéro

2025-01-19
Cours Essentiel de Robotique et ROS 2 Open Source : Apprenez ROS 2 à partir de zéro

Henki Robotics, en collaboration avec l'Université d'Eastern Finlande, a mis à disposition un cours de robotique ROS 2 open source pour débutants. Le cours couvre les concepts essentiels de ROS 2, la simulation Gazebo, le SLAM, la navigation et plus encore, le tout dans un environnement conteneurisé basé sur Docker, éliminant ainsi le besoin d'installation préalable. Les exercices pratiques et l'accent mis sur l'application pratique font de ce cours une option idéale pour les débutants souhaitant acquérir rapidement les compétences nécessaires au développement robotique moderne.

Développement Cours Open Source

Suppression des types dans Node.js : simplification du développement TypeScript

2025-01-19
Suppression des types dans Node.js : simplification du développement TypeScript

Node.js v23.6.0 introduit une fonctionnalité expérimentale attendue depuis longtemps, la suppression des types (Type Stripping), visant à simplifier l'utilisation de TypeScript en permettant l'exécution de code TypeScript sans configuration supplémentaire. Cette fonctionnalité supprime les informations de type du code TypeScript, évitant ainsi les configurations et les vérifications de type fastidieuses, et améliorant ainsi l'efficacité du développement. Bien que des compromis aient été faits pour la compatibilité et les performances, comme la non-prise en charge de certaines fonctionnalités TypeScript complexes, cette fonctionnalité améliore considérablement l'expérience développeur et ouvre la voie à la popularisation de TypeScript dans l'écosystème Node.js.

Développement Suppression des types

Google publie OSV-SCALIBR : une bibliothèque puissante d’analyse de composition logicielle

2025-01-19
Google publie OSV-SCALIBR : une bibliothèque puissante d’analyse de composition logicielle

Google a publié OSV-SCALIBR, une bibliothèque extensible d’analyse de composition logicielle (SCA) permettant de scanner les paquets installés, les binaires autonomes et le code source à la recherche de vulnérabilités. Elle prend en charge de nombreux langages de programmation et gestionnaires de paquets, et génère des listes de composants logiciels (SBOM). OSV-SCALIBR est le moteur SCA principal utilisé en interne par Google et est désormais open source, avec des plans pour l’intégrer à OSV-Scanner afin d’obtenir une interface en ligne de commande plus robuste.

Développement Sécurité logicielle

Guide de programmation réseau Linux : Plongeon approfondi dans la programmation de sockets

2025-01-19
Guide de programmation réseau Linux : Plongeon approfondi dans la programmation de sockets

Ce guide fournit une explication complète de la programmation réseau sous Linux, en se concentrant sur la programmation de sockets. L’auteur remarque que de nombreuses ressources en ligne manquent de clarté et que les exemples de code ne couvrent souvent que les bases, d’où la création de ce tutoriel qui offre des instructions claires et de nombreux exemples. Les sujets abordés incluent les types de sockets, l’adressage, les API (getprotobyname(), getservbyname(), getaddrinfo(), htonl(), htons(), ntohl(), ntohs(), socket(), setsockopt(), bind(), listen(), accept(), connect(), recv(), send(), close()), les modèles client-serveur (client HTTP simple, client-serveur basé sur TCP, client-serveur TCP multithread, client-serveur basé sur UDP), des techniques avancées (sockets non bloquantes, multiplexage E/S synchrone avec select() et poll(), diffusion de messages), et la mise en réseau sécurisée avec libcurl et OpenSSL.

Développement Programmation Réseau

Le Livre du Fuzzing : Automatisation des Tests Logiciels

2025-01-19
Le Livre du Fuzzing : Automatisation des Tests Logiciels

Le Livre du Fuzzing est un guide complet sur les tests logiciels automatisés, axé sur les techniques de fuzzing. Il couvre diverses méthodes de fuzzing, notamment le fuzzing lexical, syntaxique et sémantique, avec des exemples de code exécutable pour un apprentissage pratique. Que vous soyez testeur logiciel, ingénieur sécurité ou développeur, ce livre vous permet de générer automatiquement des cas de test, d'améliorer la qualité du logiciel et de détecter des bogues cachés.

Construire une base de données en 3000 lignes de code Go : de zéro dépendance aux requêtes SQL

2025-01-19
Construire une base de données en 3000 lignes de code Go : de zéro dépendance aux requêtes SQL

Cet article détaille la création d'une petite base de données en 3000 lignes de code Go, à partir de zéro. L'auteur explique les concepts clés, en commençant par l'atomicité contre la perte de courant (obtenue grâce à des journaux d'ajout uniquement et des sommes de contrôle) et l'indexation efficace utilisant des structures de données comme les arbres B+. Le processus est expliqué étape par étape, couvrant la création d'un stockage KV en ajout uniquement, la récupération d'espace, les opérations de base de données relationnelles (requêtes ponctuelles/par plage, index secondaires), le contrôle de la concurrence et un langage de requête similaire à SQL. L'ensemble du processus est documenté dans un livre, disponible gratuitement en ligne.

Développement

Redécouverte du joyau d'Apple Newton : Open Dylan

2025-01-19

Open Dylan est un langage de programmation fonctionnel orienté objet, descendant du langage Dylan d'Apple, initialement créé pour l'assistant numérique personnel Newton. Combinant les points forts de Scheme et de CLOS, sans la syntaxe Lisp, il est conçu pour une génération de code machine efficace. Cet article présente la documentation complète d'Open Dylan, y compris des tutoriels, des manuels de référence et une documentation de bibliothèque étendue, ainsi qu'un espace de jeu en ligne pour une expérimentation rapide. Que vous appreniez un nouveau langage ou que vous exploriez des paradigmes de programmation efficaces, Open Dylan mérite le détour.

Développement

Visionneuse d'images en terminal : l'odyssée d'un programmeur

2025-01-19

Un programmeur se lance dans une aventure complexe pour créer la visionneuse d'images en terminal parfaite. En partant de l'affichage simple des pixels, il explore les subtilités du chargement et du rendu de différents formats d'images (JPEG, PNG, GIF, AVIF, JPEG XL, HEIC, ETC, BC, OpenEXR, etc.), rencontrant des obstacles imprévus : des normes de format incohérentes, des bibliothèques mal documentées, la complexité du traitement des images HDR, les nuances de la gestion des couleurs et les limites des protocoles de sortie du terminal. Il finit par surmonter ces défis pour créer une visionneuse d'images performante, développant une profonde appréciation de la complexité et de la fascination des graphiques informatiques.

Développement affichage terminal
1 2 181 182 183 185 187 188 189 214 215