Saturday, July 11, 2020

My Custom Precision Bass

Kit

  • Kit from BYO
    • The tuners and bridge are of better quality than expected (They are better than the one found on a Fender Squire PJ Bass Affinity).
    • Inserting the neck in the body was not a problem but required multiple tries, though one of the pre-drilled holes was not perfectly aligned, the mounting plate is not straight.
    • One fret on the D string needs correction
    • The pickup is also surprisingly good. It does not sound like a Seymour  Duncan '60s Pride. But it is clear (I will post a recording later and experimentation with different pickups)
    • So far I was able to set up the action to a low level
    • The bass is very enjoyable to play
    • I still have to finalize the intonation. When I positioned the bridge I setup the saddle halfway, hopefully, I will have enough length
  • Things I missed
    • I should have given more attention to sanding the body, I am not sure how I missed it, but in the end, there were more scratch and some hole. The body
    • Applying a stain before painting may have been better for the coloring. In the back I coloring is uneven, it seems part of the wood absorbed more or less the paint. I did not spend has many coats of paint in the back than in the front and it shows.
    • Building a painting stand for the body like in this Video would have avoided some bumps when applying the Vernis?
  • Most Challenging
    • I probably mounted and un-mounted the neck 6 times, before I found the perfect position (these things require practice). But I could tell right away that it was a perfect feat and the not so perfect drilled holes created some issues
    • Mounting the bridge was challenging because it has to be positioned perfectly in a 90-degree angle, and I am not sure what I could have used as a reference point.
      Watch some video on youtube about that.
      I found that one person was applying some painting tape around the bridge areas and then draw some line with a ruler using as reference the right and left side of the neck.
      The distance is not a problem we know it is  17 ". The problem is the Angle.
      Once I drew the lines I centered the 4 main holes from the bridges on the lines.
    • Since I positioned the pickups after the bridge there was a little miss alignment between the strings and the pickups. This can be corrected by moving the saddle, but it may affect intonation. It may be better to mount the pickup before the bridge and use some light write to verify the alignment

Painting

The oil paint used took at least 5 full days to dry. So it took 2 weeks to finish the painting.
Using the Vernis spraymax (see above link), is relatively easy

Painting days

First coat on Saturday 1 and second coat Sunday 1.
Took up to Friday to dry.

Third coat on Saturday 2
Took up to Friday to dry.

Vernis on Saturday 3
Take 24 hours to dry



The Vernis looks better in these pictures taken 1 hour after applying than in the end.




Assembling


aa











Reference Videos





Thursday, March 5, 2020

Winmerge for git


Download tool from
https://winmerge.org/downloads/?lang=en


Update file C:\Users\username\.gitconfig
with configuration (from https://gist.github.com/shawndumas/6158524)

[mergetool]
    prompt = false
    keepBackup = false
    keepTemporaries = false

[merge]
    tool = winmerge

[mergetool "winmerge"]
    name = WinMerge
    trustExitCode = true
    cmd = "/c/Program\\ Files\\ \\(x86\\)/WinMerge/WinMergeU.exe" -u -e -dl \"Local\" -dr \"Remote\" $LOCAL $REMOTE $MERGED

[diff]
    tool = winmerge

[difftool "winmerge"]
    name = WinMerge
    trustExitCode = true
    cmd = "/c/Program\\ Files\\ \\(x86\\)/WinMerge/WinMergeU.exe" -u -e $LOCAL $REMOTE


Thursday, December 19, 2019

rxjs Reminders

 Links

This blog post is based on the free training video "Learn RxJS in 60 Minutes for Beginners - Free Crash Course" from Gary Simon.


Code Samples



Cold Observable

import { Observable } from 'rxjs/Observable';

// Observable producer actived when subscribed
const observable = Observable.create((observer: any) => {
    try {
        observer.next('Hey guys!'); // Emit a value
        observer.next('how are you?'); // Emit a value
        let counter = 0;
        setInterval(() => {
            observer.next(`I am good [${counter++}]`);
        }, 2000);
        // observer.complete();
        // observer.next('This will not be sent'); 
    }
    catch(ex) {
        observer.error(ex);
    }
});

const observer = observable.subscribe(
    (x:any) => { addItem(`[1] ${x}`); }, // next
    (error:any) => { addItem(`[ERROR]${error}`); }, // error
    () => { addItem('Completed'); }, // complete
);

const observer2 = observable.subscribe(
    (x:any) => { addItem(`[2] ${x}`); }, // next
);
observer.add(observer2); // Now observer2 will be canceled when observer is unsubscribed
//observer.remove(observer2); // undo the add

setTimeout(() => { // Canceled the observer to receive value after 6 seconds
    observer.unsubscribe();
}, 6001);

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

Warn Observable

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/share';

// Observable producer actived when subscribed - Cold Observer
const observable = Observable.create((observer: any) => {
    try {
        observer.next('Hey guys!'); // Emit a value
        observer.next('how are you?'); // Emit a value
        let counter = 0;
        setInterval(() => {
            observer.next(`'I am good [${counter++}]`);
        }, 2000);
    }
    catch(ex) {
        observer.error(ex);
    }
}).share(); // Make it a warn Observable, subscriber only receive 
            // the stream from the moment they subscribed rather 
            // then from the beginning

const observer = observable.subscribe(
    (x:any) => { addItem(`[1] ${x}`); }, // next
    (error:any) => { addItem(`[ERROR]${error}`); }, // error
    () => { addItem('Completed'); }, // complete
);

setTimeout(() => {
    const observer2 = observable.subscribe(
        (x:any) => { addItem(`[2] ${x}`); }, // next
    );
}, 1000);

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

Hot Observable

import { Observable } from 'rxjs/Observable';
import { fromEvent } from 'rxjs/Observable/fromEvent';

// Create hot Observable
const observable = fromEvent(document, 'mousemove');
setTimeout(() => {
    const subscription = observable.subscribe(
        (x:any) => { addItem(x); }
    );
}, 2000);

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

Subject

import { Subject } from 'rxjs/Subject';

// A subject is an observable that can also emit values
const subject = new Subject();

subject.subscribe( 
    (data) => addItem(`Observer 1: ${data}`), // Subscribe call back/notification
    (err) => addItem(err),
    () => addItem(`Observer 1 Completed`)
);

subject.next('this first thing has been sent'); // Emit a value

const observer2 = subject.subscribe( // Add a second observer, will only receice new value emitted
    (data) => addItem(`Observer 2: ${data}`)
);

subject.next('this SECOND thing has been sent');
subject.next('this THIRD thing has been sent');

observer2.unsubscribe();

subject.next('this FINAL thing has been sent');

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

BehaviorSubject

import { BehaviorSubject } from 'rxjs/BehaviorSubject';

// A subject is an observable that can also emit values
const subject = new BehaviorSubject('First');

subject.subscribe(
    (data) => addItem(`Observer 1: ${data}`), // Subscribe call back/notification
    (err) => addItem(err),
    () => addItem(`Observer 1 Completed`)
);

subject.next('this first thing has been sent'); // Emit a value
subject.next('...Observer 2 is about to subscribe'); // Emit a value

const observer2 = subject.subscribe( // Add a second observer, will start receiving from the LAST value emitted before subscription
    (data) => addItem(`Observer 2: ${data}`)
);

subject.next('this SECOND thing has been sent');
subject.next('this THIRD thing has been sent');

observer2.unsubscribe();

subject.next('this FINAL thing has been sent');

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

ReplaySubject

import { ReplaySubject } from 'rxjs/ReplaySubject';

// A subject is an observable that can also emit values
const subject = new ReplaySubject(2); // <= Number of values to send to new observer

subject.subscribe(
    (data) => addItem(`Observer 1: ${data}`), // Subscribe call back/notification
    (err) => addItem(err),
    () => addItem(`Observer 1 Completed`)
);

subject.next('this first thing has been sent'); // Emit a value
subject.next('Another thing has been sent'); // Emit a value, will be received by both observer
subject.next('...Observer 2 is about to subscribe'); // Emit a value, will be received by both observer

const observer2 = subject.subscribe( // Add a second observer, will start receiving from the LAST value emitted before subscription
    (data) => addItem(`Observer 2: ${data}`)
);

subject.next('this SECOND thing has been sent');
subject.next('this THIRD thing has been sent');

observer2.unsubscribe();

subject.next('this FINAL thing has been sent');

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

AsyncSubject

import { AsyncSubject } from 'rxjs/AsyncSubject';

// With AsyncSubject all values are sent only when the Observable is completed.
const subject = new AsyncSubject();

subject.subscribe(
    (data) => addItem(`Observer 1: ${data}`), // Subscribe call back/notification
    (err) => addItem(err),
    () => addItem(`Observer 1 Completed`)
);
let i = 1;
let intervalId = setInterval(() => { 
    if(i < 10) subject.next(i++);
    subject.complete();
}, 200); // Emit a integer value every 100 ms

setTimeout(() => {
    const observer2 = subject.subscribe( // Add a second observer, will start receiving from the 30 values, within the last 200 emitted before subscription
        (data) => addItem(`Observer 2: ${data}`)
    );
}, 1600);

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

Merge Operator

import { Observable } from 'rxjs/Observable';
import { merge } from 'rxjs/observable/merge';

const observable = Observable.create((observer: any) => {
    observer.next(`Hey guys`);
});
const observable2 = Observable.create((observer: any) => {
    observer.next(`How is it going?`);
});

const newObservable = merge(observable, observable2);

newObservable.subscribe((x:any) => {
    addItem(x);
});

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

Map Operator

import { Observable } from 'rxjs/Observable';
import { merge } from 'rxjs/observable/merge';

/* 
    RX JS OPERATOR: 
    https://rxjs-dev.firebaseapp.com/api/operators
    https://rxjs-dev.firebaseapp.com/guide/operators
*/

const observable = Observable.create((observer: any) => {
    observer.next(`Hey guys`);
});
const observable2 = Observable.create((observer: any) => {
    observer.next(`How is it going?`);
});

const newObservable = merge(observable, observable2);

newObservable.subscribe((x:any) => {
    addItem(x);
});

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

Pluck Operator

import { from } from 'rxjs/Observable/from';
import 'rxjs/add/operator/pluck';

from([
    { first:'Gary', last: 'Simon', age:34 },
    { first:'Frederic', last: 'Torres', age:35 },
])
    .pluck('first')
    .subscribe((firstName:string) => {
        addItem(firstName);
    });
    
function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

SkipUntil Operator

import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { interval } from 'rxjs/Observable/interval';
import 'rxjs/add/operator/skipUntil';

const observable1 = Observable.create((data: any) => { // data is an Observable
    let i=1;
    setInterval(() => {
        data.next(i++);
    }, 1000);
});

const observable2 = new Subject();
setTimeout(() => {
    observable2.next('Hey!');
}, 3500);

const newObservable = observable1.skipUntil(observable2);
newObservable.subscribe((x: number) => {
    addItem(x);
}); 

function addItem(val:any) {
    var node = document.createElement("li");
    node.appendChild(document.createTextNode(val));
    document.getElementById("output").appendChild(node);
}

Wednesday, September 18, 2019

React Hooks ~ Quick Practice

Overview


Reading and practicing React 16 hooks (useState and useEffect)

Source Code


/*
  About React Hooks
  Introducing Hooks - https://reactjs.org/docs/hooks-intro.html
  https://reactjs.org/docs/hooks-overview.html
  Using the Effect Hook - https://reactjs.org/docs/hooks-effect.html
*/
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
    // Create a property message stored in the component state
    // and a funtion setMessage to update the value
    const [message, setMessage] = useState("no message!");
    // Create a property previousMessage stored in the component state
    const [previousMessage, setPreviousMessage] = useState(null);
    // Create a property counter stored in the component state
    const [counter, setCounter] = useState(0);

    // Everytime the component update, this function is executed
    // Similar to componentDidMount and componentDidUpdate
    useEffect(() => {
        console.log(`[useEffect] -- GLOBAL -- message:${message}, counter:${counter}`);
    });

    // Everytime the component update because the property message has changed,
    // this function is executed
    useEffect(() => {
        // Only run when message changed
        console.log(`[useEffect] -- message:${message}, counter:${counter}`);

        // We return a function that will be executed before the parent
        // function is executed the next time. This is used for clean up.
        return () => {
            // Run when the component unmount,
            // as well as before re-running the effect due to a subsequent render
            setPreviousMessage(message);
            console.log(`[useEffect Previous] -- message:${message}, counter:${counter}`);
        };
    }, [message]);

    const click = () => {
        setMessage(` msg-${Date.now()}`);
    };

    const onClickCounter = value => {
        setCounter(counter + value);
    };

    return (
        

React useState, useEffect

Counter: {counter}



Message: {message}

previousMessage: {previousMessage}

); } const rootElement = document.getElementById("root"); ReactDOM.render(, rootElement);

Saturday, June 29, 2019

Difference between JavaScript Engines

Spread operator

JavaScriptCore the JavaScript engine in SAFARI Mac Os and iOS as well as in Chrome iOS implements the spread operator differently than V8 (Chrome) or Spider Monkey (Firefox).


o1 = { id1:{ isSelected: false}, id2:{ isSelected: false}, id3:{ isSelected: false} }
selected = { id2:{ isSelected: true} }
r = {...o1, ...selected}

// Chrome Windows, FireFox Windows, Chrome MacOs
// The order of the key/property is preserved based on variable o1
{ id1:{ isSelected: false}, id2:{ isSelected: true}, id3:{ isSelected: false} }

// Safari Mac, Safari iOS, Chrome iOS
// The order of the key/property is NOT preserved based on variable o1
// The key/property id2 is now at the end
{ id1:{ isSelected: false}, id3:{ isSelected: false}, id2:{ isSelected: true}  }


This is not a bug, as you should not assume the order of the key/property in an dictionary or object.

Issue sorting array of objects in different browser 

Chrome and Firefix Windows will not return the same result.