Compare commits

...

3 Commits

8 changed files with 345 additions and 57 deletions

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="4.233336mm"
height="4.233336mm"
viewBox="0 0 4.233336 4.233336"
version="1.1"
id="svg2475"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="list-icon.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview2477"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="23.318967"
inkscape:cx="5.2532343"
inkscape:cy="9.5630307"
inkscape:window-width="1920"
inkscape:window-height="1006"
inkscape:window-x="0"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2472" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-152.75743,-23.863736)">
<circle
style="fill:none;fill-opacity:1;stroke:#202228;stroke-width:0.639316;stroke-linejoin:round;stroke-opacity:1;paint-order:fill markers stroke"
id="path1850"
cx="155.16"
cy="26.429564"
r="0.92050833" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -54,6 +54,7 @@ import { Project } from '@/model/projects';
import * as skills from '@/service/skills';
import * as projects from '@/service/projects';
import { go } from '@/service/scroller';
import { Locales } from '@/locales';
interface Details {
icon: string|null;
@ -174,7 +175,7 @@ export default class SkillPicker extends Vue {
icon,
title: this.$t(skillLabel(id)).toString(),
projects: projects.bySkill(id),
text: skill.info,
text: skill.info[this.$i18n.locale as Locales],
};
}

View File

@ -61,10 +61,10 @@
</div>
<div :key="'end-'+proj.name" class='end'>
<template v-if='proj.stopped_at != null'>
{{ $t('project.end') }} {{ proj.stopped_at | short_date }} <span>{{ elapsed(proj.stopped_at) }}</span>
{{ $t('project.end') }} {{ proj.stopped_at | short_date }} <span>{{ duration(proj.started_at, proj.stopped_at, true) }}</span>
</template>
<template v-else>
{{ $t('project.still') }}
{{ $t('project.still') }} <span>{{ duration(proj.started_at, new Date(), false) }}</span>
</template>
</div>
@ -90,17 +90,16 @@ interface TimeDiff {
plural: string; // plural translation label
}
// returns a TimeDiff from a date. Holds the time elapsed until now in the most
// returns a TimeDiff from a date. Holds the time elapsed until @stop in the most
// broad unit that is greater than 0.
function getTimeDiff(date: Date): TimeDiff {
function getTimeDiff(start: Date, stop: Date): TimeDiff {
const minute = 60 * 1000;
const hour = 60 * minute;
const day = 24 * hour;
const month = 30 * day;
const year = 365 * day;
const now = new Date();
const diff = now.getTime() - date.getTime();
const diff = stop.getTime() - start.getTime();
if ( diff < 0 ) {
return {diff: 0, one: 'time.some', plural: 'time.some'};
@ -153,7 +152,7 @@ export default class Timeline extends Vue {
protected elapsed(date: Date): string {
const fmt = 'time.diff-format';
const td = getTimeDiff(date);
const td = getTimeDiff(date, new Date());
const diff = Math.floor(td.diff);
@ -168,6 +167,22 @@ export default class Timeline extends Vue {
return this.$t(fmt, { elapsed: this.$t(td.one, { n: diff }) }).toString();
}
protected duration(start: Date, stop: Date, ended: boolean): string {
const fmt = ended ? 'time.dur-format' : 'time.cur-format';
const td = getTimeDiff(start, stop);
const diff = Math.floor(td.diff);
if( diff == 0 ){
return this.$t(fmt, { duration: this.$t(td.one) }).toString();
}
if( diff > 1 ){ // plural
return this.$t(fmt, { duration: this.$t(td.plural, { n: diff }) }).toString();
}
// singular
return this.$t(fmt, { duration: this.$t(td.one, { n: diff }) }).toString();
}
private onScroll(e: Event) {
const target = e.target as HTMLElement;
const header = this.$refs.header as HTMLElement;
@ -214,6 +229,7 @@ export default class Timeline extends Vue {
width: 100%;
height: $header-height;
font-size: 1em;
background: #202228;
box-shadow: 0 0 1em transparent;
@ -229,6 +245,8 @@ export default class Timeline extends Vue {
border-radius .2s ease-in-out,
box-shadow .1s ease-in-out;
overflow: hidden;
img {
width: $logo-size;
height: $logo-size;
@ -245,6 +263,8 @@ export default class Timeline extends Vue {
margin: auto;
flex-flow: row nowrap;
justify-content: space-around;
align-items: center;
h3 {
color: #fff;
@ -473,6 +493,7 @@ export default class Timeline extends Vue {
padding-bottom: 2em;
margin-bottom: 1.5em;
color: #c1c1c1;
background: #323841;
border: .1rem solid #45454b;
@ -540,4 +561,25 @@ export default class Timeline extends Vue {
}
</style>
<style lang="scss">
// for translated styles
.desc {
b {
color: #fff;
}
i {
color: #d5d5d5;
}
li {
list-style-type: none;
list-style-image: url('../assets/timeline/list-icon.svg');
margin-left: 1.5em;
}
}
</style>

View File

@ -76,6 +76,8 @@
"skill.rnd": "R&D",
"skill.teamlead": "Team Lead",
"time.dur-format": "took {duration}",
"time.cur-format": "since {duration}",
"time.diff-format": "{elapsed} ago",
"time.some": "sometime",

View File

@ -38,7 +38,8 @@
"skill.concurrency": "Programmation Concurrente",
"skill.teamlead": "Chef d'équipe",
"time.dur-format": "a duré {duration}",
"time.cur-format": "depuis {duration}",
"time.diff-format": "il y a {elapsed}",
"time.some": "un moment",

View File

@ -86,4 +86,49 @@ export const Projects: Project[] = [
doc: { name: 'pkg.go.dev/github.com/xdrm-io/aicra', link: 'https://pkg.go.dev/github.com/xdrm-io/aicra' },
commits: 535,
},
{
name: 'go-ws',
client: null,
skills: [s.Go, s.Websocket, s.OpenSource, s.Opti],
started_at: new Date(2018, 4, 24),
stopped_at: new Date(2021, 6, 21),
info: {
[Locales.EN]: 'Research project to learn more about websockets. I developed a websocket client and server using the RFC as only guidance.<br><br>I did some optimizations to provide a performant solution based on the idiomatic way of dealing with asynchronous resources (channels). By the way I used gorilla/websocket later and I don\'t understand why everything in the API is synchronous ?!<br><br>"I know websockets"',
[Locales.FR]: 'Projet de recherche pour mieux comprendre les websockets. J\'ai développé un client et un serveur websocket avec la RFC comme seul guide.<br><br>J\'ai aussi fait une passe optimisation pour avoir une solution performante basée sur la manière idiomatique (Go) de gérer la concurrence (channels). D\'ailleurs j\'ai utilisé gorilla/websocket plus tard, et je ne comprends pas pourquoi toute l\'api est synchrone ?!<br><br>"I know websockets"',
},
source: { name: 'git.xdrm.io/go/ws', link: 'https://git.xdrm.io/go/ws' },
doc: { name: 'pkg.go.dev/git.xdrm.io/go/ws', link: 'https://pkg.go.dev/git.xdrm.io/go/ws' },
commits: 114
},
{
name: 'SMMP (LogAuth)',
client: null,
skills: [s.Php, s.UIUX, s.Css, s.Js, s.Ajax, s.Web, s.MariaDB, s.Git, s.Inkscape],
started_at: new Date(2017, 1, 18),
stopped_at: new Date(2018, 11, 5),
info: {
[Locales.EN]: 'I conducted the LogAuth project back in 2017 for a French branch of an international carrier and logistics company. The project aims to provide a solution to track their warehouse\'s users and vehicles.<br><br>I developed:<ul><li><b>SMMP</b> <i>(Secure Management & Monitoring Platform)</i> : a web interface accessible on the internet to manage the warehouse</li><li><b>SATS</b> <i>(Secure Authentication & Tracking System)</i> : Raspberry Pi hardware & software to interface with vehicles and provide an RFID authentication for users with logging abilities.</li><li><b>setup</b> : A tool project that builds a fully-functional micro sd card for a new SATS (custom credentials, id, features, plugins).</li></ul><br><br>The SMMP is a website developped with a PHP backend and vanilla frontend (no lib). It manages groups of users and groups of machines. Some groups of users can be authorized to do some actions on some groups of machines. A page allows to browse the access history in real-time.<br><br>Also the website allowed for new features on-the-fly by using a generic database model that can define what feature read or write what GPIO pin on the RaspBerry Pi. Machine state management was also defined by the generic database model.',
[Locales.FR]: 'J\'ai réalisé le projet <b>LogAuth</b> en 2017 pour la branche française d\'une entreprise internationale de transport et logistique. Le projet vise à fournir une solution afin de suivre et gérer les accès des utilisateurs aux machines d\'un entrepot.<br><br>J\'ai développé:<ul><li><b>SMMP</b> <i>(Secure Management & Monitoring Platform)</i> : un site web accessible sur Internet pour la gestion par entrepôt.</li><li><b>SATS</b> <i>(Secure Authentication & Tracking System)</i> : le hardware et logiciel pour un Raspberry Pi qui est embarqué sur chaque machine. Il fournit une authentification RFID aux utilisateurs avec historique.</li><li><b>setup</b> : Un outil permettant d\'écrire un carte microSD functionnelle pour chaque nouveau Raspberry à ajouter au système (authentification sur-mesure, id, fonctionnalités, plugins).</li></ul><br><br>La plateforme SMMP est un site web développé avec un backend PHP et un frontend vanilla (pas de librairie). Elle permet la gestion de groupes d\'utilisateurs et de groupes de machines. Des actions peuvent être configurées pour des groupes d\'utilisateurs sur des groupes de machines. Une page permet de parcourir l\'historique des accès en temps réel.<br><br>De plus, le site permet l\'ajout de nouvelle fonctionnalités en l\'état grâce à un modèle de base de données générique qui permet directement de définir des entrées/sorties du Raspberry Pi. La machine à état est aussi définie dans le modèle générique en base.',
},
source: { name: 'git.xdrm.io/logauth/smmp', link: 'https://git.xdrm.io/logauth/smmp' },
doc: null,
commits: 114
},
{
name: 'SATS (LogAuth)',
client: null,
skills: [s.RaspBerry, s.Electronics, s.Systemd, s.Python, s.Php, s.Linux, s.Bash, s.Crypto, s.Git,],
started_at: new Date(2017, 1, 18),
stopped_at: new Date(2018, 11, 5),
info: {
[Locales.EN]: 'I conducted the LogAuth project back in 2017 for a French branch of an international carrier and logistics company. The project aims to provide a solution to track their warehouse\'s users and vehicles.<br><br>I developed:<ul><li><b>SMMP</b> <i>(Secure Management & Monitoring Platform)</i> : a web interface accessible on the internet to manage the warehouse</li><li><b>SATS</b> <i>(Secure Authentication & Tracking System)</i> : Raspberry Pi hardware & software to interface with vehicles and provide an RFID authentication for users with logging abilities.</li><li><b>setup</b> : A tool project that builds a fully-functional micro sd card for a new SATS (custom credentials, id, features, plugins).</li></ul><br><br>The SATS consists of a hardware and its associated firmware. The firmware is a set of programs launched through a complex systemd state machine to go through the stages : boot, network connection, update check, update, init IO, the daemon (main loop).<br><br>It grants or denies access when an RFID card is detected, the access list is regularly fetched from the SMMP api. It is able to update and fetch new features from the network. It stores every access (or attempt), manages and tracks the machine state over time.<br><br>I made a few PCBs for the SATS in order to interface the Raspberry properly.<br><br>I also had to design my own authentication system to provide a robust and attack-proof communication between SATS and the SMMP. It avoids key theft, request forgery and allows for resynchronization after an attack or a theft.',
[Locales.FR]: 'J\'ai réalisé le projet <b>LogAuth</b> en 2017 pour la branche française d\'une entreprise internationale de transport et logistique. Le projet vise à fournir une solution afin de suivre et gérer les accès des utilisateurs aux machines d\'un entrepot.<br><br>J\'ai développé:<ul><li><b>SMMP</b> <i>(Secure Management & Monitoring Platform)</i> : un site web accessible sur Internet pour la gestion par entrepôt.</li><li><b>SATS</b> <i>(Secure Authentication & Tracking System)</i> : le hardware et logiciel pour un Raspberry Pi qui est embarqué sur chaque machine. Il fournit une authentification RFID aux utilisateurs avec historique.</li><li><b>setup</b> : Un outil permettant d\'écrire un carte microSD functionnelle pour chaque nouveau Raspberry à ajouter au système (authentification sur-mesure, id, fonctionnalités, plugins).</li></ul><br><br>Le systyème SATS consiste en un shield (carte éléctronique) ajoutée au Raspberry Pi ainsi qu\'un firmware. Le firmware est composé de plusieurs programmes lancés à travers une machine à état complexe dans systemd afin d\'accéder aux différentes phases : boot, connexion réseau, vérification de mise à jour, mise à jour, init E/S, le démon (boucle principale).<br><br>Il autorise ou non les accès quand une carte RFID est détectée, la liste des accès est mise à jour périodiquement depuis l\'api SMMP. Il est capable de se mettre à jour et de charger de nouvelles fonctionnalités depuis le réseau. Il enregistre tous les accès (ou tentatives), gère et monitore l\'état de la machine en temps réel.<br><br>J\'ai du réaliser plusieurs PCBs afin que le SATS s\'interface correctement avec le Raspberry.<br><br>J\'ai pu lors de ce projet concevoir mon propre système d\'authentication afin de protéger les communications entre les SATS et le SMMP. Il évite notamment le vol de clé, le détournement de requêtes, et permet une resynchronisation sécurisée après une attaque ou un vol.',
},
source: { name: 'git.xdrm.io/logauth/sats', link: 'https://git.xdrm.io/logauth/sats' },
doc: null,
commits: 114
}
];

View File

@ -1,3 +1,5 @@
import { Locales } from "@/locales";
export enum tID {
MariaDB,
Postgres,
@ -134,7 +136,7 @@ export interface tSkill {
icon: string|null;
link: string;
tags: tTag[];
info: string;
info: { [loc in Locales]: string };
}
export type tSkills = { [id in tID]: tSkill };
@ -144,283 +146,421 @@ export const Skills: tSkills = {
link: 'https://mariadb.org',
icon: 'skills/mariadb.svg',
tags: [tTag.Web, tTag.Storage],
info: 'I started using mysql then MariaDB as my first introduction to SQL, mostly when I started learning web with PHP. I now prefer using postgreSQL instead as it tends to be more robust and performant overall.',
info: {
[Locales.EN]: 'I started using mysql then MariaDB as my first introduction to SQL, mostly when I started learning web with PHP. I now prefer using postgreSQL instead as it tends to be more robust and performant overall.',
[Locales.FR]: 'J\'ai commencé à utiliser MySQL puis MariaDB en introduction à SQL, principalement quand j\'ai commencé à apprendre le développement web avec PHP. J\'utilise maintenant plutôt PostgreSQL car je le trouve plus robuste et performant.',
}
},
[tID.Postgres]: {
link: 'https://postgresql.org',
icon: 'skills/postgres.svg',
tags: [tTag.Web, tTag.Storage],
info: 'My main choice of dbms when using sql orfor relational databases. Had some experience with it mainly with go services with docker.',
info: {
[Locales.EN]: 'My main choice of dbms when using sql orfor relational databases. Had some experience with it mainly with go services with docker.',
[Locales.FR]: 'Mon choix de prédilection quand il s\'agit de DBMS sql ou de base relationnelle. Je l\'ai pas mal utilisé principalement pour des services go avec docker et docker-compose.',
}
},
[tID.Mongo]: {
link: 'https://mongodb.com',
icon: 'skills/mongo.svg',
tags: [tTag.Web, tTag.Storage],
info: 'I learned it during my Master\'s degree. I used advanced Mongo with schema validation and complex filter requests. I find this technology really interesting over SQL, but I find classical relational databases are easier to comprehend and I am more used to it.',
info: {
[Locales.EN]: 'I learned it during my Master\'s degree. I used advanced Mongo with schema validation and complex filter requests. I find this technology really interesting over SQL, but I find classical relational databases are easier to comprehend and I am more used to it.',
[Locales.FR]: 'J\'ai appris et utilisé Mongo pendant mon Master, je n\'ai pas eu de réelle occasion de l\'utiliser depuis. J\'ai pu utiliser la version "robuste" de Mongo : validation de schéma and requêtes avec filtres complexes.<br><br>Je trouve cette technologie une intéressante alternative au SQL "classique", mais les bases relationnelles sont à mon avis plus facile à apréhender, puis j\'y suis habitué.',
}
},
[tID.Vue]: {
link: 'https://vuejs.org',
icon: 'skills/vue.svg',
tags: [tTag.Web, tTag.UI],
info: 'I started learning Vue (.js) back in 2016, and never stopped practicing since then for personal and professional projects. I view it as a better alternative than angular which provides you with a strict framework that can lack flexibility among teams and projects.<br><br>Vue makes it your responsability to properly structure your project which I like to take care of myself, as it tends to provide a better workflow adjusted for every project.<br><br>It is my top choice when considering a web framework for rendering pages.',
info: {
[Locales.EN]: 'I started learning Vue (.js) back in 2016, and never stopped practicing since then for personal and professional projects. I view it as a better alternative than angular which provides you with a strict framework that can lack flexibility among teams and projects.<br><br>Vue makes it your responsability to properly structure your project which I like to take care of myself, as it tends to provide a better workflow adjusted for every project.<br><br>It is my top choice when considering a web framework for rendering pages.',
[Locales.FR]: 'J\'ai découvert Vue en 2016, et n\'ai jamais arrêté de l\'utiliser depuis tant pour mes projets perso que professionnels. Je vois Vue comme une meilleure alternative qu\'Angular qui, lui, fournit un cadre de travail strict qui manque de flexibilité aux équipes et projets.<br><br>Vue vous rend la responsabilité de structurer correctement vos projets, ce que j\'apprécie faire moi-même, je trouve que ça pousse à un meilleur workflow (ajusté à chaque projet).<br><br>C\'est moi choix de prédilection en tant que framework web pour faire du rendu.',
}
},
[tID.Angular]: {
link: 'https://angular.io',
icon: 'skills/angular.svg',
tags: [tTag.Web, tTag.UI],
info: 'I used it only once to break it apart in a R&D project. I had to "hack" it in order to inject services and components on-the-fly.<br><br>You had a kind of App store where you could install modules. The Angular-powered website would inject new navigation menus, pages and services according to the modules you had installed.<br><br>I do not like Angular, as I think Vue.js does a better job achieving the same goal with a cleaner API, and does not force you to embrace the Angular/Google way of coding and organizing things.',
info: {
[Locales.EN]: 'I used it only once to break it apart in a R&D project. I had to "hack" it in order to inject services and components on-the-fly.<br><br>You had a kind of App store where you could install modules. The Angular-powered website would inject new navigation menus, pages and services according to the modules you had installed.<br><br>I do not like Angular, as I think Vue.js does a better job achieving the same goal with a cleaner API, and does not force you to embrace the Angular/Google way of coding and organizing things.',
[Locales.FR]: 'Je l\'ai découvert de la manière forte pour un projet de R&D projet. J\'ai du le "hacker" afin de pouvoir y injecter des services et composants au runtime.<br><br>J\'ai du faire un genre d\'App store où il était possible d\'installer des modules. Le site web Angular se voyait ensuite injecté les éléments de navigation, les pages et services en fonction des modules installés.<br><br>Je n\'apprécie pas Angular, je pense que Vue fait un meilleur travail pour achever le même but avec une interface plus propre. Je trouve qu\'Angular force les devs à se plier à la manière Angular/Google de programmer et d\'organiser les choses.',
},
},
[tID.Parcel]: {
link: 'https://parceljs.org/',
icon: 'skills/parcel.svg',
tags: [tTag.Web],
info: 'I used it often back in my Master\'s Degree period along with PHP backends. It allows to get away from webpack which I find overly complicated and a major point of failure for most frontends.<br><br>I haven\'t used it in a while but would highly consider it as it has no real prerequisite.',
info: {
[Locales.EN]: 'I used it often back in my Master\'s Degree period along with PHP backends. It allows to get away from webpack which I find overly complicated and a major point of failure for most frontends.<br><br>I haven\'t used it in a while but would highly consider it as it has no real prerequisite.',
[Locales.FR]: 'Beaucoup utilisé pendant le Master, souvent pour des projets web avec un backend PHP. Permet de s\'affranchir de webpack, ce que je trouve plutôt bénéfique car trop complexe et souvent un point-of-failure majeur.<br><br>Je ne l\'ai pas utilisé depuis un moment mais je le garde en tête comme alternative sans prérequis pour les projets web.',
}
},
[tID.Cordova]: {
link: 'https://cordova.apache.org/',
icon: 'skills/cordova.svg',
tags: [tTag.System, tTag.Web, tTag.Mobile],
info: 'I used it often to transform single-page applications into android, iOS or desktop apps at low cost. I haven\'t needed this kind of software for a while, it might now be favorable to use Capacitor or other "alternatives".',
info: {
[Locales.EN]:'I used it often to transform single-page applications into android, iOS or desktop apps at low cost. I haven\'t needed this kind of software for a while, it might now be favorable to use Capacitor or other "alternatives".',
[Locales.FR]:'Je l\'ai beaucoup utilisé pour transformer mes applis SPA (Single Page Application) en applications Android, iOS ou de bureau a moindre coût. Je n\'en ai pas eu besoin depuis un moment, il serait sûrement judicieux de m\'intéresser aux nouvelles alternatives plus à jour telles que Capacitor.',
},
},
[tID.Webpack]: {
link: 'https://webpack.js.org/',
icon: 'skills/webpack.svg',
tags: [tTag.Web],
info: '... I used it a lot because it is often required. But I hate that it is so complex that most users use it without understanding what is really does. I avoid it whenever possible, the issue can be transposed to node_modules and the whole node ecosystem.',
info: {
[Locales.EN]: '... I used it a lot because it is often required. But I hate that it is so complex that most users use it without understanding what is really does. I avoid it whenever possible, the issue can be transposed to node_modules and the whole node ecosystem.',
[Locales.FR]: '... J\'ai été forcé de beaucoup l\'utiliser mais jamais par choix ! C\'est un outil très puissant, mais je n\'aime pas que ce soit aussi complexe et que la plupart des utilisateurs (moi inclus) l\'utilisent sans vraiment comprendre ce que ça fait réellement. Je l\'évite dès que possible, cette problématique peut être transposée à node_modules et l\'écosystème node en général.',
}
},
[tID.WebGL]: {
link: 'https://www.khronos.org/webgl/',
icon: null,
tags: [tTag.Web],
info: 'I used it during my graduation years, the potential is great but I need to find a time to explore what\'s new.',
info: {
[Locales.EN]: 'I used it during my graduation years, the potential is great but I need to find a time to explore what\'s new.',
[Locales.FR]: 'Utilisé à plusieurs reprises pendant mes études, il y a un gros potentiel mais il me faudrait trouver le temps d\'explorer les nouveautés et utilisation.',
}
},
[tID.AudioAPI]: {
link: 'https://webaudio.github.io/web-audio-api/',
icon: null,
tags: [tTag.Web],
info: 'I used it mainly to build a discord clone (audio and video full-duplex streaming) as a school project. I also tried the Fourier transform to build nice graphics (c.f. Soundcloud) but have not succeeded at the time.',
info: {
[Locales.EN]: 'I used it mainly to build a discord clone (audio and video full-duplex streaming) as a school project. I also tried the Fourier transform to build nice graphics (c.f. Soundcloud) but have not succeeded at the time.',
[Locales.FR]: 'Je l\'ai notamment utilisée pour un projet clone de Discord (audio et video en streaming full-duplex) pendant mes études. J\'ai aussi beaucoup joué avec pour essayer d\'implémenter la transformée de Fourier afin de produire un visuel de lecture audio (c.f. Soundcloud) mais je n\'ai pas réussi à l\'époque.',
}
},
[tID.Websocket]: {
link: 'https://tools.ietf.org/html/rfc6455',
icon: null,
tags: [tTag.Web, tTag.Network, tTag.IoT],
info: 'I use them whenever possible to avoid the classical expensive polling.<br><br>I also created my own websocket client & server implementation in Go following nothing but the RFC for learning purposes.<br><br>I\'ve used, designed and implemented websocket communications among personal and professional projects.',
info: {
[Locales.EN]: 'I use them whenever possible to avoid the classical expensive polling.<br><br>I also created my own websocket client & server implementation in Go following nothing but the RFC for learning purposes.<br><br>I\'ve used, designed and implemented websocket communications among personal and professional projects.',
[Locales.FR]: 'Je les utilise dès que possible plutôt que faire du polling coûteux pour rien.<br><br>J\'ai aussi créé ma propre implémentation de client et serveur en Go en suivant juste la RFC afin d\'avoir une meilleure appréhension du fonctionnement et des limites.<br><br>J\'ai eu plusieurs l\'occasion de concevoir et implémenter des systèmes de communications basés sur les websocket que ce soit pour des projets perso ou pro.',
}
},
[tID.Docker]: {
link: 'https://docker.com',
icon: 'skills/docker.svg',
tags: [tTag.Web, tTag.System],
info: 'I am using it for a while now. Most of my go projects use it as it costs no memory for your executable (multi-stage build from scratch) and allows for isolation and a better control over the running environment. I am learning docker a bit more every time I use it. It is often coupled with docker-compose in my projects.',
info: {
[Locales.EN]: 'I am using it for a while now. Most of my go projects use it as it costs no memory for your executable (multi-stage build from scratch) and allows for isolation and a better control over the running environment.<br><br>I am learning docker a bit more every time I use it. It is often coupled with docker-compose in my projects.',
[Locales.FR]: 'J\'utilise docker assez régulièrement depuis des années. La plupart de mes projets en go en tirent parti car cela permet de construire des containers "multi-plateforme" sans que ç pèse plus lourd que l\'exécutable (multi-stage build from scratch). Docker aussi permet à mes devs en go de l\'isolation et un meilleur contrôle de l\'environnement.<br><br>J\'étends mes connaissances à chaque nouveau projet, je l\'utilise aussi beaucoup via docker-compose.',
}
},
[tID.Bash]: {
link: 'https://www.gnu.org/software/bash/',
icon: null,
tags: [tTag.System],
info: 'Felt in love with GNU/linux and its ecosystem a while back (was 14yo back then) and I\'ve never stopped. I\'m often the linux/bash guy of the team.<br><br>I use it extensively to automate anything a human can do as it avoids a lot of mistakes in most workflows.',
info: {
[Locales.EN]: 'Felt in love with GNU/linux and its ecosystem a while back (was 14yo back then) and I\'ve never stopped. I\'m often the linux/bash guy of the team.<br><br>I use it extensively to automate anything a human can do as it avoids a lot of mistakes in most workflows.',
[Locales.FR]: 'Je suis tombé amoureux de GNU/Linux et son écosystème depuis un moment (à 14 ans) et je n\'ai pas déchanté depuis. Je suis souvent le "linux/bash guy" de l\'équipe.<br><br>J\'utilise le bash de manière déraisonnable pour automatiser tout ce que les humains peuvent faire, mais sans les erreurs, dans la plupart de mes workflows.',
}
},
[tID.Linux]: {
link: 'https://www.linux.org',
icon: 'skills/linux.svg',
tags: [tTag.System],
info: 'Felt in love with GNU/linux and its ecosystem a while back (was 14yo back then) and I\'ve never stopped. <br><br>Linux has been my main OS choice since then. I stepped through Ubuntu, Debian, Manjaro, Elementary, Tails (live), and I am now on Solus for a few years.',
info: {
[Locales.EN]: 'Felt in love with GNU/linux and its ecosystem a while back (was 14yo back then) and I\'ve never stopped. <br><br>Linux has been my main OS choice since then. I stepped through Ubuntu, Debian, Manjaro, Elementary, Tails (live), and I am now on Solus for a few years.',
[Locales.FR]: 'Je suis tombé amoureux de GNU/Linux et son écosystème depuis un moment (à 14 ans) et je n\'ai pas déchanté depuis. <br><br>Linux est mon OS depuis. Je suis passé par Ubuntu, Debian, Manjaro, Elementary, Tails (live), je suis maintenant sur Solus depuis quelques années.',
},
},
[tID.Systemd]: {
link: 'https://freedesktop.org/wiki/Software/systemd/',
icon: null,
tags: [tTag.System],
info: '',
info: {
[Locales.EN]: 'I had the chance to dive deep into systemd for the LogAuth project. I had to define a complex structure for some Raspberry Pi to be independent, featuring services, paths, sockets, dependencies, requirements, etc.<br><br>Often used but rarely understood, I like its flexibility and have used it in many projects upon the production deployment.',
[Locales.FR]: 'J\'ai eu l\'occasion de plonger dans les tréfonds de systemd pour le projet LogAuth. J\'ai du concevoir et implémenter une structure complexe pour des Raspberry Pi "embarqués" en utilisant les services, paths, sockets, dépendences, ordres d\'éxécution, etc.<br><br>Souvent utilisé mais rarement compris, j\'apprécie sa puissance et sa flexibilité, je l\'ai souvent utilisé dans mes projets web pour le déploiement sur l\'environnement de production.',
},
},
[tID.Git]: {
link: 'https://git-scm.com/',
icon: 'skills/git.svg',
tags: [tTag.System, tTag.Organization],
info: '',
info: {
[Locales.EN]: 'What to say about git ?!',
[Locales.FR]: 'Quoi dire sur git ?!',
},
},
[tID.Rpm]: {
link: 'https://rpm.org/',
icon: null,
tags: [tTag.System],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.RaspBerry]: {
link: 'https://raspberrypi.org',
icon: 'skills/raspberry.svg',
tags: [tTag.System, tTag.IoT],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Arduino]: {
link: 'https://arduino.cc',
icon: 'skills/arduino.svg',
tags: [tTag.System, tTag.IoT],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Php]: {
link: 'https://www.php.net',
icon: 'skills/php.svg',
tags: [tTag.Language, tTag.Web, tTag.IoT],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Html]: {
link: 'https://www.w3.org/standards/webdesign/htmlcss',
icon: 'skills/html.svg',
tags: [tTag.Language, tTag.Web, tTag.UI],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Css]: {
link: 'https://www.w3.org/standards/webdesign/htmlcss',
icon: 'skills/css.svg',
tags: [tTag.Language, tTag.Web, tTag.UI],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Js]: {
link: 'http://www.ecma-international.org/publications-and-standards/standards/ecma-262/',
icon: 'skills/js.svg',
tags: [tTag.Language, tTag.Web, tTag.UI],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Ajax]: {
link: 'https://www.w3schools.com/xml/ajax_intro.asp',
icon: null,
tags: [tTag.Web, tTag.Network],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Ts]: {
link: 'https://www.typescript.org/',
icon: 'skills/ts.svg',
tags: [tTag.Language, tTag.Web, tTag.UI],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.C]: {
link: 'https://www.open-std.org/jtc1/sc22/wg14/',
icon: 'skills/c.svg',
tags: [tTag.Language, tTag.System],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Cpp]: {
link: 'https://isocpp.org/',
icon: 'skills/cpp.svg',
tags: [tTag.Language, tTag.System],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Python]: {
link: 'https://python.org/',
icon: 'skills/python.svg',
tags: [tTag.Language, tTag.System],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Go]: {
link: 'https://go.dev',
icon: 'skills/go.svg',
tags: [tTag.Language, tTag.System, tTag.IoT, tTag.Network],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Qt]: {
link: 'https://qt.io',
icon: 'skills/qt.svg',
tags: [tTag.Language, tTag.System, tTag.IoT, tTag.Network],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.OpenSource]: {
link: 'https://opensource.org/',
icon: null,
tags: [tTag.Human],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Electronics]: {
link: 'https://en.wikipedia.org/wiki/Electronics',
icon: 'skills/electronics.svg',
tags: [tTag.Other, tTag.IoT],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Web]: {
link: 'https://en.wikipedia.org/wiki/World_Wide_Web',
icon: null,
tags: [tTag.Web],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Rest]: {
link: 'https://en.wikipedia.org/wiki/Representational_state_transfer',
icon: null,
tags: [tTag.Web, tTag.Network],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Crypto]: {
link: 'https://en.wikipedia.org/wiki/Cryptography',
icon: 'skills/security.svg',
tags: [tTag.System, tTag.Network],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.ImageProcessing]: {
link: 'https://en.wikipedia.org/wiki/Digital_image_processing',
icon: 'skills/image-processing.svg',
tags: [tTag.System],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.AI]: {
link: 'https://en.wikipedia.org/wiki/Artificial_intelligence',
icon: null,
tags: [tTag.Other],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.DeepLearning]: {
link: 'https://en.wikipedia.org/wiki/Deep_learning',
icon: null,
tags: [tTag.Other],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.NeuralNetwork]: {
link: 'https://en.wikipedia.org/wiki/Artificial_neural_network',
icon: null,
tags: [tTag.Other],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Opti]: {
link: 'https://en.wikipedia.org/wiki/Program_optimization',
icon: 'skills/opti.svg',
tags: [tTag.System, tTag.Network],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Sockets]: {
link: 'https://en.wikipedia.org/wiki/Computer_network_programming',
icon: null,
tags: [tTag.System, tTag.Network, tTag.IoT, tTag.Web],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Concurrency]: {
link: 'https://en.wikipedia.org/wiki/Concurrent_computing',
icon: null,
tags: [tTag.System, tTag.Network],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.UIUX]: {
link: 'https://en.wikipedia.org/wiki/UX',
icon: null,
tags: [tTag.System, tTag.Web, tTag.IoT],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.Inkscape]: {
link: 'https://inkscape.org/',
icon: 'skills/inkscape.svg',
tags: [tTag.UI, tTag.Web, tTag.Organization],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.RnD]: {
link: 'https://en.wikipedia.org/wiki/R&D',
icon: null,
tags: [tTag.Organization, tTag.Other],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
[tID.TeamLead]: {
link: 'https://en.wikipedia.org/wiki/Team_leader',
icon: null,
tags: [tTag.Organization, tTag.Human,],
info: '',
info: {
[Locales.EN]: '',
[Locales.FR]: '',
},
},
};

View File

@ -1,4 +1,4 @@
import { tID, Skills, tSkill, tTag } from '@/model/skills';
import { tID, Skills, tSkill, tTag, skillLabel } from '@/model/skills';
let availCache: tID[]|null = null;
let tagsCache: tTag[]|null = null;
@ -17,6 +17,13 @@ export function available(): tID[] {
}
availCache.push(id);
}
availCache.sort( (a: tID, b: tID) => {
const aname = skillLabel(a);
const bname = skillLabel(b);
if( aname < bname ){ return -1; }
if( aname > bname ){ return 1; }
return 0;
});
return availCache;
}