<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: François-Emmanuel CORTES</title>
    <description>The latest articles on DEV Community by François-Emmanuel CORTES (@hefeust).</description>
    <link>https://dev.to/hefeust</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F926783%2Fcdee01dd-952d-4205-9c2e-2d108b523ecd.jpeg</url>
      <title>DEV Community: François-Emmanuel CORTES</title>
      <link>https://dev.to/hefeust</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hefeust"/>
    <language>en</language>
    <item>
      <title>Playing with QUID string keys</title>
      <dc:creator>François-Emmanuel CORTES</dc:creator>
      <pubDate>Wed, 04 Jun 2025 23:08:23 +0000</pubDate>
      <link>https://dev.to/hefeust/playing-with-quid-string-keys-3fjk</link>
      <guid>https://dev.to/hefeust/playing-with-quid-string-keys-3fjk</guid>
      <description>&lt;p&gt;[TODO: Duck Blocks Manager article (urbex-dbm)]&lt;br&gt;
&lt;a href="https://github.com/hefeust/urbex-quids" rel="noopener noreferrer"&gt;Browse the code repo for project urbex-quids&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are not perfect, of course, but they are easulyscalable  to many RGBA  color space points !&lt;/p&gt;

&lt;h1&gt;
  
  
  Playing with QUID string keys
&lt;/h1&gt;

&lt;p&gt;I call those QUID string keys for "Quasi-Unique IDentifiers" : these randomized string keymaps are not ~100% guaranteed (cryptographocally speaking) to be unique during runtime, but the program  can use them easily and safely to identify a bunch of data items, acommodating with possible collisions between consecutive computed values of the keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;Let's have a very big collections of blocks stored data inside a JS/TS Map:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Block = { /* user data */ }

const blocks: Map &amp;lt;string, Block&amp;gt; = new Map ()

blocks.set ('abcd', { x: 1 })
blocks.set ('ef12', { y: 2 })
blocks.set ('3456', { z: 3 })        
blocks.set ('7890', { w: 4 })        

// oops we erased some useful data !
blocks.set ('abcd', { bad: '#ERROR!' })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We want enough keys to avoid collision and data loss; both we also want to keep human-readability for keys.&lt;/p&gt;

&lt;h1&gt;
  
  
  UUIDs ? No, just QUIDs !
&lt;/h1&gt;

&lt;p&gt;Of course you probably think to a node library UUID-like to produce keys in the form: XXXX-XXXX-4YXX-XXXX-XXXXXXXXXXX ?If so you can watch&lt;/p&gt;

&lt;p&gt;(see tutos #random #generator #etc...)&lt;/p&gt;

&lt;p&gt;But do you really need for your todolists, a lightweb game a such level of uniqness and unpredictility in yout keys ?&lt;/p&gt;

&lt;p&gt;If not, just try the QUID approach !&lt;/p&gt;

&lt;p&gt;Let's figure out N-digits hexadecimal strings, such as "900dcafe": "bada55e5" or "c0cac01a".&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LENGTH  available values&lt;br&gt;
2       256&lt;br&gt;
4       65536 (= 256 * 256)&lt;br&gt;
8       ~ 4.2 * Math.pow (10, 9)&lt;br&gt;
16      ... isn't it enough ??&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Computing&lt;br&gt;
&lt;/h1&gt;

&lt;p&gt;Since access to Map is algorithmically time-constant O(1) complexity, let's compute new keys against user map keys.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// "phantom" property...&lt;br&gt;
export type QUID = string &amp;amp; { __quid: void }

&lt;p&gt;export  const nextQUID = (exists: (qtest: QUID) =&amp;gt; boolean): QUID =&amp;gt; {&lt;br&gt;
    let counter: number = 0&lt;br&gt;
    let qtest: QUID&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;do {
    const str = [0, 1, 2, 3].map ((_) =&amp;amp;gt; {
        return Math.floor (256 * Math.random ())
            .toString (16)
            .padStart (2, '0')

    }).reduce ((acc, str) =&amp;amp;gt; acc += str, '')

    qtest = fromString (str)    

    if (counter &amp;amp;gt; 1000) {
        throw new Error ('#QUID_LOOP!')
    }

    counter++
} while (exists (qtest))

return qtest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;} &lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Storage impacts&lt;br&gt;
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Performance considerations
&lt;/h1&gt;

&lt;p&gt;Since Map.has is O(1) time complexity and 8-kzngth hexa-string could address 4.2 * Math.pow (10, 9), collision risks are limited, same for loops in nextQUID function.&lt;/p&gt;

&lt;p&gt;So can be efficient.&lt;/p&gt;

&lt;p&gt;Happy coding !&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>random</category>
      <category>map</category>
    </item>
    <item>
      <title>[At Run Time] Adaptative Log Function</title>
      <dc:creator>François-Emmanuel CORTES</dc:creator>
      <pubDate>Sun, 03 Nov 2024 22:41:33 +0000</pubDate>
      <link>https://dev.to/hefeust/at-run-time-adaptative-log-function-56dm</link>
      <guid>https://dev.to/hefeust/at-run-time-adaptative-log-function-56dm</guid>
      <description>&lt;p&gt;When debugging some buge coding project, you want sometimes to drop a &lt;em&gt;console.log()&lt;/em&gt; calls to track some varaible and errors, to figure out what is happening during program execution, especially nearby potential tricky sections of it; something like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function danger (a: number, b: number) {
    console.log ('### (title "h3") the dangerous function is here...')

    try {
        return a / b
    } catch (err) {
        console.log ('posssible divisoion by zero !')
        console.log ({a, b })

        throw new Error ('#DIVIDE_BY_ZERO')
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This approach gives you the ability to see the error at its location. &lt;/p&gt;

&lt;p&gt;But  the more code grows and the more logging calls occurrences grows together...  and when comes And that produces time-consuming task to remove these calls (manually or not): lot of work in perpsective, and risks to waste time introducing some garbage (characters typos) and need to fix it again.&lt;/p&gt;

&lt;h1&gt;
  
  
  Logger class (first idea)
&lt;/h1&gt;

&lt;p&gt;The idea for now is to add a Logger/Debugger class to filter &lt;em&gt;console.log&lt;/em&gt; calls and shutdown its messages when the production phase comes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function danger (a: number, b: number) {
    const debug = Debug.getInstance ()

    debug.level (3).title ('the dangerous function is here...')

    try {
        return a / b
    } catch (err) {
        debug.level (2).title ('posssible divisoion by zero !')
        debug.level (3).dump ({a, b })

        throw new Error ('#DIVIDE_BY_ZERO')
    }
}    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: the singelton instance exposes a &lt;em&gt;level&lt;/em&gt; method that returns a fluent interface, backed by some closure and bounding pattern, and wrap &lt;em&gt;console.log&lt;/em&gt; calls:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Debug class
protected verbosity = 0

protected log (effective: number, something) {
    if (this.verbosity &amp;lt; effective ) {
        // here we effectively log in the browser
        console.log (something)
    }
}

protected title (level: number, text: string) {
   const message = '#'.repat (level) + ' ' + text
   this.log (level, message)
}

protected dump (level: number,something) {
   this.log (level, something)
}

public level (wandered: number) {
    return {
        title: this.title.bind (this, this.verbosiry),
        dump: this.dump.bind (this, this.verbosiry),            
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;No it's OK logginh process is filterd properly. Adapt it now ?&lt;/p&gt;

&lt;h1&gt;
  
  
  Adaptative ? OK for now !
&lt;/h1&gt;

&lt;p&gt;Declare a setter for &lt;em&gt;thos.verbosity&lt;/em&gt; value: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// default behaviour:  shutdown all logs (silent)
public adapt (wantered: number = 0) {
    this.verbosity = wandered
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  USE CASE: dangerous functions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Phase of self-tests of program: log enough stuff;&lt;/li&gt;
&lt;li&gt;Phase Production: log normally and minimally (0: silently, when possible);&lt;/li&gt;
&lt;li&gt;Increase &lt;em&gt;drastrically&lt;/em&gt; verbosity just before throwing errors:&lt;/li&gt;
&lt;li&gt;if error is catched properly at a higher level in call stack , adapt level to 0, to turn it off again !
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    function danger (a: number, b: number) {
        const debug = Debug.getInstance ()

        debug.level (3).title ('the dangerous function is here...')

        try {
            return a / b
        } catch (err) {
            // now we have all errors log:
            debug.adapt (10)
            debug.level (2).title ('posssible divisoion by zero !')
            debug.level (3).dump ({a, b })

            throw new Error ('#DIVIDE_BY_ZERO')
        }
    }    

    function process (iterations: number) {
        const debug = Debug.getInstance ()

        for (let a = 0; a &amp;lt; iterations; a++) {
            for (let b = 0; b &amp;lt; iterations; b++) {}        
                // print all results
                // debug.level (0).dump (danger (a,b ))

                // or log anyway, print, do whatever with results...
                console.log (danger (an b))
            }
    }

    // *** caller code (main routine) ***
    const debug = Debug.getInstance ()       

    // self tests
    debug.adapt (1)
    process (1)    

    // produiuction phase: NO MPGS
    debug.adapt (0)
    process (1000 * 1000)    

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Doing like this, we adapt the logging mechanism to see clearly what is happening diring tests phase and after dangerous runtime error occurrence, the rest of (normal) run time we don't pollute the briwser's console anymore, neither altering performances anymore.&lt;/p&gt;

&lt;p&gt;Happy coding !&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>beginners</category>
      <category>log</category>
      <category>runtime</category>
    </item>
    <item>
      <title>SvelteKit responsive helper</title>
      <dc:creator>François-Emmanuel CORTES</dc:creator>
      <pubDate>Mon, 15 Jul 2024 08:59:11 +0000</pubDate>
      <link>https://dev.to/hefeust/sveltekit-responsive-helper-283c</link>
      <guid>https://dev.to/hefeust/sveltekit-responsive-helper-283c</guid>
      <description>&lt;p&gt;Tired of writing complicated media queries ? SvelteKit windiow directives  can help you simplifying them programtically. With the help of this layout component ViewoirtSettingsCatcher component  and its associated store ViewportSettingsStore, they are presented in this topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Grabbing viewport dimensions
&lt;/h2&gt;

&lt;p&gt;Very simple use of svlete:window directive's bindings:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- ViewportSettingsCatchr.svelte --&amp;gt;
&amp;lt;script lang="ts"&amp;gt;
    let innerWidth: number = 1600
    let innerHeight: number = 1200
&amp;lt;/script&amp;gt;

&amp;lt;svelte:window bind:innerWidth vind:nnerHeight /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Registering inside store
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$: ViewportSettingsStore.register ({ innerWidth, innerHeight })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  the associated computation store
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { writable} from 'svelte/store'
const { subscribe, update  } = writable ({
    innerWidth: 1600, 
    innerHeight: 1200,
    ratio: 16/12, 
    orientation: 'landscape',   
    wide: false
})

function register ({ innerWidth, innerHeight }) {
    const ratio = innerWidth / innerHeight
    const orientation = ratio &amp;gt;= 1 ? 'landscape' : 'portrait'
    const wide = (ratio &amp;gt; 2) || (ratio &amp;lt; 0.5)

    update ((state) =&amp;gt; {
        return {
            innerWidth, 
            innerHeight,
            orientation,
            ratio,
            wide
        }
    })
}

export const ViewportSettingsStore = {
    subscribe, register 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  simple usage
&lt;/h2&gt;

&lt;p&gt;Just import ViewportSettingsStore in your componentr&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class:wide={ $ViewportSettingsStore.orientation = === 'landscape' } /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Et voilà... That's done.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>responsive</category>
      <category>store</category>
      <category>sveltekit</category>
    </item>
    <item>
      <title>Chess colored tactical helper</title>
      <dc:creator>François-Emmanuel CORTES</dc:creator>
      <pubDate>Fri, 28 Jun 2024 19:43:40 +0000</pubDate>
      <link>https://dev.to/hefeust/chess-colored-tactical-helper-1cj6</link>
      <guid>https://dev.to/hefeust/chess-colored-tactical-helper-1cj6</guid>
      <description>&lt;p&gt;Hi there,&lt;/p&gt;

&lt;p&gt;I'am re-building my project ColorChess.&lt;/p&gt;

&lt;p&gt;It's about chess playing with some colored helpers to enhance tactical equilibriums between players sides on the board.&lt;/p&gt;

&lt;p&gt;I initiated this project with JavaScript in early year 2010. I opted  the magical combo SvelteKit + TypeScript for the new version in 2024.&lt;/p&gt;

&lt;p&gt;You can see the 2010 prototype repo on my Github:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://github.com/hefeust"&gt;http://github.com/hefeust&lt;/a&gt; --&amp;gt; just by following "Colorchess"link.&lt;/p&gt;

&lt;p&gt;My goal is to build a new site during this summer and if possible, implementing an original playing bot.&lt;/p&gt;

&lt;p&gt;Regards, hefeust&lt;/p&gt;

</description>
      <category>chess</category>
      <category>typescript</category>
      <category>sveltekit</category>
      <category>tactics</category>
    </item>
    <item>
      <title>SVG SvelteKit game engine project</title>
      <dc:creator>François-Emmanuel CORTES</dc:creator>
      <pubDate>Mon, 25 Sep 2023 22:04:46 +0000</pubDate>
      <link>https://dev.to/hefeust/svg-sveltekit-game-engine-project-1npi</link>
      <guid>https://dev.to/hefeust/svg-sveltekit-game-engine-project-1npi</guid>
      <description>&lt;h1&gt;
  
  
  SVG-based isometric game engine for SvelteKit
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The ECS (Entity-Component-System) part
&lt;/h2&gt;

&lt;p&gt;It is designed to be intuitive to use out-of-the-box: comprehensive API with simple verbs.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Code examples: instantiate
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ecs = engine.ECS ('world-name', { /* options */ })&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Component schemas&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Just a plain object with a name and a test properties. Rzqr us a validation callback. Some validators like 3D poosition and velocity are predefined. T o add a new custom validation schema, just provide it to the schema function :&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ecs.schema ((c) =&amp;gt; {&lt;br&gt;
    name: 'game-healh-component', &lt;br&gt;
    test: (c) =&amp;gt; {&lt;br&gt;
        // a component filtering callback,&lt;br&gt;
        if (Number (c.healt) !== c.healt) return false
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    uf (c.health &amp;amp;lt; 0) return false
    if (c.health &amp;amp;gt; 1000) return false

    return true
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;})&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Entites&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;using an init callback&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ecs.entity ('layer-name-is-player', (e) =&amp;gt; {&lt;br&gt;
    // pre-defined or custom components&lt;br&gt;
    e.component ('position', { x: 50, y: 50; z: 10 })&lt;br&gt;
    e.component ('game-healtt-component',  health: 100 {})

&lt;p&gt;})&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Systems&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Using the query utilituy funtion inside entity updater:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;e.system ('bonus-elixir-bottle', (query) =&amp;gt; {&lt;br&gt;
    query ()&lt;br&gt;
})&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  The main updater:&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;To be triggered inside SvelteKit event loop, acting as a game loop:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$: ecs.update ()&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  The rendering part (SVG)&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Integrated with SvelteKit stores.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems to solve before the lib is ready
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Correct integration inside SvelteKit app structure
&lt;/li&gt;
&lt;li&gt;Optimizing stores dependcy graph&lt;/li&gt;
&lt;li&gt;Sprite Topological sorting&lt;/li&gt;
&lt;li&gt;In-place level editing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo and sources
&lt;/h2&gt;

&lt;p&gt;(2025-06-05: site no longer avaailabl, sorry, but still coding this project)&lt;/p&gt;

</description>
      <category>isometric</category>
      <category>game</category>
      <category>engine</category>
      <category>javascript</category>
    </item>
    <item>
      <title>A tiny bash file viewer with line numbering</title>
      <dc:creator>François-Emmanuel CORTES</dc:creator>
      <pubDate>Sun, 16 Apr 2023 21:06:57 +0000</pubDate>
      <link>https://dev.to/hefeust/a-very-simple-bash-file-inspector-cc5</link>
      <guid>https://dev.to/hefeust/a-very-simple-bash-file-inspector-cc5</guid>
      <description>&lt;p&gt;SSometimes when you build and run a Javascript file in Node, some TypeErrors can pass through ESBuild checks and they're difficult to understand directly... l&lt;/p&gt;

&lt;p&gt;To visualize a screen portion of code you can try writing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
max=$(( $1+10 ))
length=20
cat -n $2 | head --lines=${max} | tail --lines=${length}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;save it to "see-lines.sh" and setup it in your project structure and invoke it with the error stack trace line number:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./see-lines 421 dist/index-bundled.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et voilà !&lt;/p&gt;

</description>
      <category>bash</category>
      <category>beginners</category>
      <category>tuto</category>
    </item>
    <item>
      <title>Easy Log Facilities for JavaScript</title>
      <dc:creator>François-Emmanuel CORTES</dc:creator>
      <pubDate>Sat, 08 Oct 2022 18:39:41 +0000</pubDate>
      <link>https://dev.to/hefeust/easy-log-facilities-for-javascript-48p2</link>
      <guid>https://dev.to/hefeust/easy-log-facilities-for-javascript-48p2</guid>
      <description>&lt;p&gt;Here are some log debugging facilities exposed for JS.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. console.log (arg1, arg2, ..., argn)
&lt;/h2&gt;

&lt;p&gt;console.log can take more than one argument. If it is the case, it would make logs as much as separate arguments count.&lt;/p&gt;

&lt;h2&gt;
  
  
   2. console.log ({ ...props })
&lt;/h2&gt;

&lt;p&gt;You can either pass an object or a property bag object and it will be logged as well. Remember that if an object does not have an explicit toString() method it will output something like "[object Object]" when concatenated in a message string, and could be useless.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// example
const a = 1
const b = 2
const c = 3

// shorthand object notation
const item = { a, b, c }

// instead of:
console.log ('The item is ' + item)

// prefer: 
console.log ('the item is:', item)

// or: 
console.log ({ item })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  debug flag for factory functions
&lt;/h2&gt;

&lt;p&gt;You can pass to a factory function a debug flag, and log if it is true, just with logical AND!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let debug = true

const factoryFun = ({ x, y, debug }) =&amp;gt; {
    const point = { x, y }

    point.distance = (other) =&amp;gt; {
        const dx = Math.abs (this.x - other.x)
        const dy = Math.abs (this.y - other.y)

        debug &amp;amp;&amp;amp; console.log ('computing distance between another point')

        return Math.sqrt (dx*dx + dy*dy)
    }

    debug &amp;amp;&amp;amp; console.log ('factory')

    return point
}

const point = factoryFun ({ x:4, y:2, debug })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Adjustable verbosity level filtering
&lt;/h2&gt;

&lt;p&gt;let level = 0 // no log !&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const bigImplFun = ({ level }) =&amp;gt; {
    const filter = (x) =&amp;gt; x &amp;gt; 0 &amp;amp;&amp;amp; x &amp;gt;= level

    filter (1) &amp;amp;&amp;amp; console.log ('log level 1')
    filter (2) &amp;amp;&amp;amp; console.log ('log level 2')
    filter (3) &amp;amp;&amp;amp; console.log ('log level 3')
}

bigImplFun ({ level: 3 })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Indentable logging messages
&lt;/h2&gt;

&lt;p&gt;Wrap it up ! If you're tired writing ampersands "&amp;amp;&amp;amp;" sequences, isolate inside a function body&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const debugx = ( level, message ) =&amp;gt; {
    const test = x &amp;gt; 0 &amp;amp;&amp;amp; x &amp;gt;= level
    const indent = '\t'.repeat (level - 1)

    test &amp;amp;&amp;amp; console.log (indent + message)
}

const BigImplModule = ({ level }) =&amp;gt; {
    const nested = () =&amp;gt; {
        debug (2, 'log level2')
    }

    const f1 = () =&amp;gt; {
        debug (1, 'log level1')
    }
    const f2 = () =&amp;gt; {
        debug (1, 'log level1')
        nested ()
    }

    const mod = { f1, f2 }
   return mod
}

let level = 0 // no debug !!!
let instance = bigImplModule ({ level })

instance.f1 ()
instance.f2 ()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et voilà ! Happy coding.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>debug</category>
    </item>
    <item>
      <title>smplie finite state machine for EcmaScript</title>
      <dc:creator>François-Emmanuel CORTES</dc:creator>
      <pubDate>Thu, 15 Sep 2022 14:07:08 +0000</pubDate>
      <link>https://dev.to/hefeust/smplie-finite-state-machine-for-ecmascript-2a5d</link>
      <guid>https://dev.to/hefeust/smplie-finite-state-machine-for-ecmascript-2a5d</guid>
      <description>&lt;h1&gt;
  
  
  Mach: flexible FSM in ECMAScript
&lt;/h1&gt;

&lt;p&gt;Hi there,&lt;/p&gt;

&lt;p&gt;I just developped a simple Finite State Machine in JS. My initial goal was to  integrate it within a SvelteKit component to provide UI state management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design and usage
&lt;/h2&gt;

&lt;p&gt;this is a single ECMAScript file; simply import it in yout code, and call the FSM () constructor with its parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import { FSM } from './FSM.js'

    const fsm = FSM ({
        debug: true,
        jumps: ({ state }) =&amp;gt; console.log ({ state }),
        success: ({ state }) =&amp;gt; console.log ('success'),
        failure: ({ state }) =&amp;gt; console.log ('failure')
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can simply define states and transition arrows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    fsm.state ({ name: 'INIT', init: true })
    fsm.state ({ name: 'TERM', term: true })
    fsm.state ({ name: 'OFF' })
    fsm.state ({ name: 'ON' })

    fsm.arrow ({ from: 'INIT', accept: 'activate', to: 'OFF'})
    fsm.arrow ({ from: 'OFF', accept: 'switch', to: 'ON'})
    fsm.arrow ({ from: 'ON', accept: 'switch', to: 'OFF'})
    fsm.arrow ({ from: 'ON', accept: "kick", to: 'TERM'})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course with this way of doing things, you can freely hydrate states and transition arrows from an external data store such a database; or modularize you FSM design according to logial tests !&lt;/p&gt;

&lt;p&gt;After all, pack the machine to run it, and read some entries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    fsm.pack ({ state: 'INIT '})

    fsm.accept ({ word: 'activate'})
    fsm.accept ({ word: 'on'})
    fsm.accept ({ word: 'kick'})

    // console.log ('success')    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementation details
&lt;/h2&gt;

&lt;p&gt;all entries (STATES and reanition arrows) are stored in the same array structure, as duck blocks. The items list is doubled by a lookup map which holds pairs (name) =&amp;gt; [array-of-indexes] for all name  inside the machine (UPPERCASED for STATES and lowercased for arrows). This shorts the time used to locate states/words blocks .&lt;/p&gt;

&lt;h2&gt;
  
  
  Further steps
&lt;/h2&gt;

&lt;p&gt;adding support for asynchronous transduction operations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    /// Here's the complete code for the Mach FSM ...


export const FSM = ({ jumping, success, failure, debug } = {}) =&amp;gt; {

    // holds STATE and ARROW items
    const entries = [{ uid: 0, def: 'ROOT' }]

    // aliases lookups table
    const lookups = new Map ()

    const runtime = {
        GUID: 0,
        state: null,  
        trace: [],
        data: null
    }

    // state definition
    const state = ({ name, init, term, payload }) =&amp;gt; {
        const def = 'STATE'
        const alias = ('' + name).toUpperCase ()
        const uid = ++runtime.GUID
        const uids = lookups.get(alias) || []
        const len = uids.length

        const item = {
            uid, def, alias, init, term, payload
        }

        if (len === 0) {
            entries.push (item)       
            lookups.set (alias, [uid])
        } else {
            throw new Error ('duplicate entry ' + uis + ' ' + alias)
        }

        if (debug) {
            if (len === 0) {
                console.log ('creating new state', { alias, uid })
            } else {
                console.log ('replacing item', { alias, uid })
            }
        }
    }

    // arrow definition
    const arrow = ({ from, accept, to, ops }) =&amp;gt; {
        const def = 'ARROW'
        const alias = ('' + accept).toLowerCase ()
        const uid = ++runtime.GUID
        const uids = lookups.get(alias) || []
        const len = uids.length

        const item = {
            uid, def, alias, from, accept, to, ops 
        }

        entries.push (item)
        uids.push (uid)
        lookups.set (alias, uids)

//        console.log ('craating arrow', { item })
   }

    // ready to run !!!
    const pack = ({ state, data }) =&amp;gt; {
        const alias = ('' + state).toUpperCase ()

        runtime.state = alias
        runtime.data = data

        if (debug) {
            console.log('Finite State Machine packing', alias) 
        }
    }

    // read entry word
    const read = ({ word, data }) =&amp;gt; {
        const alias = ('' + word).toLowerCase ()
        const uids = lookups.get (alias) || []
        let accepted = false 

        console.log ('read', { [alias]: uids.join(', ') })

        uids.map ((uid) =&amp;gt; entries [uid])
            .map ((item) =&amp;gt; {
                console.log ('MAP', { item })
                return item
            })
            .filter ((item) =&amp;gt; accepted === false)
            .filter ((item) =&amp;gt; item.def === 'ARROW')
            .filter ((item) =&amp;gt; item.from === runtime.state)
            .filter ((item) =&amp;gt; item.accept === alias)
            .map ((item) =&amp;gt; {
                const suids = lookups.get (item.to) || []
                const final = entries [suids[0]]                

                runtime.state = item.to
                runtime.trace.push (alias)
                accepted = true

                jumping &amp;amp;&amp;amp; jumping.call &amp;amp;&amp;amp; jumping.call (null, {
                    trace: runtime.trace,
                    result: runtime.data,
                    state: runtime.state,
                    word: alias                   
                })

                item.ops &amp;amp;&amp;amp; item.ios.call &amp;amp;&amp;amp; item.ops.call (null, { 
                    data, 
                    trace: runtime.trace,
                    result: runtime.data,
                    state: runtime.state,
                    word: alias                   
                })

                if (final.term) {
                    success &amp;amp;&amp;amp; success.call (null, { 
                        data, 
                        trace: runtime.trace,
                        result: runtime.data,
                        state: runtime.state,
                        word: alias                   
                    })
                }

                return true
            })

        if (accepted === false) {
            failure &amp;amp;&amp;amp; failure.call (null, { 
                data,                      
                trace: runtime.trace,
                result: runtime.data,
                state: runtime.state,
                word: alias                   
             })
        }
    }

    // return debug table as string
    const table = () =&amp;gt; {
        const texts = []

        texts.push ('~~~ Finistamach: lightweight Finite State Machine ~~~')
        texts.push ('')
        texts.push ('uid\tdef\talias\t\tmore info...')
        texts.push ('--------'.repeat(5))

        entries.map ((item) =&amp;gt; {

            if (item.def === 'STATE') {
                texts.push ([
                    item.uid, 'STATE', item.alias + '\t', 
                    (item.init ? '*init*' : '') +  (item.term ? "*term*" : "")
                ].join('\t'))
            }

            if (item.def === 'ARROW') {
                texts.push ([
                    item.uid, 'ARROW', item.alias + '\t', 
                    item.from + ' --{' + item.accept +  '}-&amp;gt; ' +  item.to
                ].join('\t'))            }
        })

        return texts.join('\n')
    }


    return {
        state, arrow,  pack, read, table
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
