Apple Macbook Pro M1 MacOS Big Sur – Missing xcrun after MacOS Update

I always face missing xcrun when I use command “git pull” after MacOS update where the OS will update xcode.

apple macbook pro M1 - missing xcrun
apple macbook pro M1 – missing xcrun

To solve this problem just install back the xcode-select via the command line.

A window will appear whether to continue to install. Just click install.

apple macbook pro M1 - install xcode-select
apple macbook pro M1 – install xcode-select

It takes around 5 minutes to download the file.

apple macbook pro M1 - download xcode select
apple macbook pro M1 – download xcode select

After installation, run again the “git pull” . This time it will work.

apple macbook pro M1 git pull success
apple macbook pro M1 git pull success

Godot 3.2.3 Grid Movement Part 2/2

I converted this Godot Grid Movement Video Tutorial into textual tutorial because I feel it is much easier to follow textual tutorial.

This is Part 2, you can view Part 1 here.

What You Will Learn From This Godot Grid Movement Tutorial

  1. How to create player sprite that move in 2D grid
  2. Create Collision walls where the player sprite cannot pass through the wall

Part 2 – Player Sprite Moves within Walls

Create Walls

i. Add child node -> Add TileMap.
ii. Set Tile Set from empty to new Tile Set.
iii. Double click on new Tile Set to change to Resource tab.
iv. Click “+” add texture (add bottom left)
v. Use the default Godot icon as the wall.
vi. Make the Icon editor window bigger by clicking on the up arrow (bottom right)
vii. Zoom in the tile set by clicking “+” at top right.
viii. Click “New Single Tile” and click grid icon to enable the grid.
ix. Select the icon if selected yellow line will appear.
x. Change color to black by clicking the “Modulate”
xi. Change RGB color to 000000

godot grid movement - create tilemap
godot grid movement – create tilemap
godot grid movement - set tile set to new tile set
godot grid movement – set tile set to new tile set
godot grid movement - double click on new tile set to set the resources
godot grid movement – double click on new tile set to set the resources
godot grid movement - add the resource
godot grid movement – add the resource
godot grid movement - use default godot icon
godot grid movement – use default godot icon
godot grid movement - click up arrow bottom rigth to make the icon editor bigger
godot grid movement – click up arrow bottom rigth to make the icon editor bigger
godot grid movement - zoom in the icon
godot grid movement – zoom in the icon
godot grid movement - click new single tile and enable the grid
godot grid movement – click new single tile and enable the grid
godot grid movement - grid enabled
godot grid movement – grid enabled
godot grid movement - change color by clicking on modulate
godot grid movement – change color by clicking on modulate
godot grid movement - change color to black where RGB 000000
godot grid movement – change color to black where RGB 000000

Add Collision to The Wall Tile Set

i. Ensure tile set is still selected (yellow outline)
ii.Click “Collision”
iii. Click the square icon
iv. The select the region within the yellow line.
v. Icon color will change to turquoise if collision is properly set.

godot grid movement - add collision square
godot grid movement – add collision square

Create The Maze

i. Click on player sprite (to go back to player scene)
ii. You will see the TileMap is black now.
iii. Check the TileMap is 64×64
iv. Click on TileMap and start populating the walls to create your own maze.

godot grid movement - wall is black
godot grid movement – wall is black
godot grid movement - ensure size is 64x64
godot grid movement – ensure size is 64×64
godot grid movement - create maze
godot grid movement – create maze

Add RayCast2D to Player Sprite

i. Right click on Player sprite -> Add child node
ii. Select RayCast2D
iii. Set the RayCast2D
– Position x = 32, y = 32 (to make centre (red plus sign))
– Enable is on
– Cast to y = 32 (to make the down blue arrow to just at the edge of the player sprite)

godot grid movement - create raycast2D
godot grid movement – create raycast2D
godot grid movement - set the raycast2D
godot grid movement – set the raycast2D

Update the Player Script

i. Click on the script icon near Player sprite
ii. Update the script based on the code below.
iii. Ensure script indentation is correct.

godot grid movement - open script
godot grid movement – open script

godot grid movemen t- update script with raycast2d p1
godot grid movemen t- update script with raycast2d p1

godot grid movemen t- update script with raycast2d p2
godot grid movemen t- update script with raycast2d p2

Run The Game

i. Click Play icon (top right)
ii. Now you can see the player sprite can’t pass through the walls.

Godot 3.2.3 Grid Movement Part 1/2

I converted this Godot Grid Movement Video Tutorial into textual tutorial because I feel it is much easier to follow textual tutorial.

What You Will Learn From This Godot Grid Movement Tutorial

  1. How to create player sprite that move in 2D grid
  2. Create Collision walls where the player sprite cannot pass through the wall

Part 1 – Make the Sprite Move

Create Node

i. Click “Other Node”
ii. Then select “Node”

godot grid movement - create node
godot grid movement – create node
godot grid movement - select node
godot grid movement – select node

Create Sprite

i. Right click “Node” -> Add child node
ii. Select Sprite
iii. Drag and drop icon.png into sprite texture at right panel
iv. At sprite panel, untick centered on
v. Click “Scene” (top menu left) then save scene as player.

godot grid movement - create sprite
godot grid movement – create sprite
godot gride movement - drag n drop icon to sprite texture
godot gride movement – drag n drop icon to sprite texture
godot grid movement - untick centered
godot grid movement – untick centered
godot grid movement - save scene as player
godot grid movement – save scene as player

Add Script to the Player sprite

i. Right click on Sprite -> Attach Script
ii. Click create on when the window open.
iii. Remove all codes except “extends Sprite”
iv. Copy the code below and paste to the script. Ensure indentation is correct.

godot grid movement - attach script
godot grid movement – attach script
godot grid movement - create script
godot grid movement – create script

godot grid movement - remove all codes except extends Sprite
godot grid movement – remove all codes except extends Sprite

godot grid movement - script part 1
godot grid movement – script part 1

godot grid movement - script part 2
godot grid movement – script part 2

Run the Scene

i. Click “Play” (top right) or F5 to run the scene.
ii. Move your arrow left, right, up and down to move the player sprite.

Part 2 Godot Grid Movement Tutorial – Make The Collision Wall and Combined with Player Sprite

TypeScript Convert unknown[] to number

I use knex to update and returning number of rows been updated. It seems that knex returning update return unknown[]. But when I do checking using typeof it is actually number.

But apparently Typescript not allowed me to simply convert it.
So below is the solution.

Typescript – Builder Pattern and Inheritance

Using Typescript, I want to make a class of Builder of abstract class and follow a Builder Pattern and the child class will implement the details.

The parent abstract class:

The child class:

If you notice, you need to change the return of build() function into child class name.

typescript builder pattern and inheritance - child class
typescript builder pattern and inheritance – child class

Selenium – This version of ChromeDriver only supports Chrome version 85 error on Ubuntu

I use Selenium web driver to scrap some website data that I need for my property analysis. In this case I use chromedriver.

When I want to run it after I upgraded my Chrome browser on Ubuntu I found this error.

My steps to resolve this

1) Check my Chrome browser version and found it is 87.

google browser version
google browser version

2) Check my chromedriver version by typing

ubuntu check chromedriver version
ubuntu check chromedriver version

I found my version is 85 not same as my browser.

3) Check the location of the chrome driver by typing

In my case I found my chrome driver at /usr/local/sbin

chrome driver location on ubuntu
chrome driver location on ubuntu

4) Download the latest chromedriver at

Google ChromeDriver Website  till version 114

5) After extracting the latest chromedriver, replace the old one.

ubuntu replace old chromedriver
ubuntu replace old chromedriver

Then when I run back my program, it works!

Programmers Quadrant or Software Developers Quadrant

I created the Programmers Quadrant to make my software developers team aware of their current skills position.

With the quadrant,  a programmer can easily visualize where are they now in term of skills.

The quadrant has Data Structure and Algorithm as its vertical axis. While Reusable Codes as it horizontal axis.

This programmers quadrant is only for someone who knows to code already. If he is still learning, he won’t be categorized under this quadrant.

Data Structure and Algorithm Vertical Axis

This axis represents how good a programmer regarding data structure or algorithm.

The better he is the higher he can go into the axis.

Given a set of requirements, a programmer must be able to identify the best data structure and algorithm to solve the requirements.

Reusable Codes Horizontal Axis

This axis how good a programmer in making a reusable codes instead of hard coded to a specific application.

A person who has good knowledge on object oriented programming, design pattern, best coding practice and follows naming convention standard.

4 Programmers Quadrants

#1 – Einstein Coder

A programmer who is very good in data structure and algorithm but at same time can produce reusable codes.

#2 – Genius Code

A programmer who can create or know what is the best data structure or algorithm to be used but his code is hard coded.

#3 – Engineer Coder

A programmer who most of the time uses third party library or technology to make its application and the code produced is reusable and easily readable.

#4 – Frankenstein Coder

A programmer who use third party library, can make an application works but he produces hard coded application and not reusable for other application and not easily readable.

Selenium Webdriver How To Increase Time Out for Page Load, Script Load or Element Locator

I couldn’t find at Stackoverflow on how to increase the timeout and the Selenium API not that easy to find on how to use it.

For Selenium WebDriver using NodeJS below is how to increase its time outs. The number is in milliseconds.

From Selenium Documentation

The following timeouts are supported (all timeouts are specified in milliseconds):

  • implicit specifies the maximum amount of time to wait for an element locator to succeed when locating elements on the page. Defaults to 0 milliseconds.
  • pageLoad specifies the maximum amount of time to wait for a page to finishing loading. Defaults to 300000 milliseconds.
  • script specifies the maximum amount of time to wait for an evaluated script to run. If set to null, the script timeout will be indefinite. Defaults to 30000 milliseconds.

Reference:
https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_Options.html

Selenium User Agent vs Normal Browser User Agent

I noticed lots of websites now implement anti robot from website scraping. Most of them using fingerprintjs.com technology where it uses browser users agent as part to detect whether it is a robot or human.

I use Selenium Webdriver to scrap few websites. When I browse the website, it shows the content but if using Selenium it shows empty content.

You can test the fingerprintjs here to check whether it detects human or robot.

If using Selenium for Chrome and Firefox , fingerprintjs will detect it as robots. However if using Selenium Safari, it detects Selenium as human.

fingerprint detect selenium for safari as human
fingerprint detect selenium for safari as human

Safari when launch by default is in incognito mode so maybe harder for fingerprintjs.com detect it.

Below are comparison between Selenium for Chrome, Firefox and Safari browsers user agent.

Legend:

Yellow colored rows means there are differences between Selenium and normal browsers user agent.

Chrome Browser

NoChrome - Normal Browser User AgentChrome - Selenium User Agent
1Host: localhostHost: localhost
2Connection: keep-aliveConnection: keep-alive
3Cache-Control: max-age=0
4Upgrade-Insecure-Requests: 1Upgrade-Insecure-Requests: 1
5User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36
6Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
7Sec-Fetch-Site: noneSec-Fetch-Site: none
8Sec-Fetch-Mode: navigateSec-Fetch-Mode: navigate
9Sec-Fetch-User: ?1Sec-Fetch-User: ?1
10Sec-Fetch-Dest: documentSec-Fetch-Dest: document
11Accept-Encoding: gzip, deflate, brAccept-Encoding: gzip, deflate, br
12Accept-Language: en-US,en;q=0.9,id;q=0.8,ms;q=0.7,fr;q=0.6Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
13Cookie: chat_uuid=1458159213.1598025760; gr_session=17411c1fd31-2125f7fe5bbd95cd; gr_reco=17411c1fd70-baa36285123101b1; utag_main=v_id:017411c1fb650017fec4094270bb03079001a07100942$_sn:4$_ss:1$_st:1598096705870$_pn:1%3Bexp-session$ses_id:1598094905870%3Bexp-session

Firefox Browser

NoFirefox - Normal Browser User AgentFirefox - Selenium User Agent
1Host: localhostHost: localhost
2User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0
3Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
4Accept-Language: en-US,en;q=0.5Accept-Language: en-US,en;q=0.5
5Accept-Encoding: gzip, deflateAccept-Encoding: gzip, deflate
6Connection: keep-aliveConnection: keep-alive
7Cookie: _ga=GA1.1.1739912853.1548032065; gr_reco=1688e9dab95-b5d644815084ad40; utag_main=v_id:01688e9dad18001ff21f0bc7b4a800052009100f0093c$_sn:7$_ss:1$_st:1594889778490$_pn:1%3Bexp-session$ses_id:1594887978490%3Bexp-session; uuid=092deff09bc14cec8f32915260380536; cto_lwid=3ff13ed0-ccf0-46a0-b3d7-8a2e1cadcb3f; cto_idcpy=752176f4-9133-4eb6-a23d-8aacb880eaee; __gads=ID=258eba7044613b5a-22a30c3f84c20074:T=1594886702:S=ALNI_MYCzBeDMjB7doBDh_F5BZztWvpLvw; chat_uuid=407415995.1568209940; cto_bundle=aJ5M6V9JZCUyRjlLVVRRMG5ucUg0RUMlMkJtYk53UXpDJTJGY0Z3b09EU1RTZHpyY0xER1o0ektySUZZdU9iQ3d5UWJsOXFqUFZ4UDlZaGF4WmR4eThta2Q2S2o1NTVFd2Ruc1lBcVNJVW1IQ1ZlN1hYWTZ1VGpCZXJIZjRnRnhnZ0lEc3VuTkg3dCUyQmtTc0ZkajQ2WnJ6JTJGR0w5T3ElMkJEa1NlbjNCZlZzc2k0eVJYVU5oOEtPTjAlM0Q; _ga_SDQJRXDGN4=GS1.1.1596669834.9.0.1596669837.0; __atuvc=0%7C28%2C1%7C29%2C0%7C30%2C0%7C31%2C1%7C32; _fbp=fb.0.1586054074356.121762323; mudahHash=ec9f3f6655e4ccc0814a616dd3ee38f75d7ce494; cto_bidid=wxF3T19jb2hMYzJ1V0dITEZHRjRxMURWMWZrSTNmaDIlMkZ3RzBxTllBczB0amZMMWFOTDg2JTJGdU8xMTQzWDNzMm9TRzh0cmJHUEZFRTR0aUJWWDZQbHA1ZFhUd042cDMlMkIxdkdpOEt6S3ZqWlZ6YUNySSUzRA; _gcl_au=1.1.919768330.1594886698; gr_session=17356a7b66b-a9389a87a3e2a370
8Upgrade-Insecure-Requests: 1 Upgrade-Insecure-Requests: 1

Safari Browser

NoSafari - Normal Browser User AgentSafari - Selenium User Agent
1Host: localhost Host: localhost
2Upgrade-Insecure-Requests: 1 Upgrade-Insecure-Requests: 1
3Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
4User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15
5Accept-Language: en-us Accept-Language: en-us
6Accept-Encoding: gzip, deflate Accept-Encoding: gzip, deflate
7Connection: keep-alive Connection: keep-alive

Conclusion

Most number of differences found in Chrome and followed by Firefox. Safari doesn’t show difference between Selenium and normal browser user agent.

Does it means, it is much easier to trick anti robot using Safari?

ChromeFirefoxSafari
310

How To Convert Javascript to TypeScript

Previously I use Babel Javascript to convert my javascript to ECMA2015. I like to program in object oriented because I learned my first programming language in C/C++ and Java.

Doing procedural language like C was much easier vs object oriented Java. But in the long run, I noticed that coding in object oriented is much easier to maintain.

Steps to Convert Javascript to TypeScript

Install TypeScript

-g to make it global so all your JavaScript programs can be migrated to TypeScript.

Create tsconfig.build.json, tsconfig.json and tslint.json

At your root project folder run the below command.

I edited my tsconfig.json as follows:

I added manually tsconfig.build.json and tslint.json

tslint.json

Change Your Existing Files Extension from .js to .ts

typescript change all js to ts extension
typescript change all js to ts extension
typescript change all js to ts extension
typescript change all js to ts extension

Amend Coding T0 Follows TypeScript

Below are few examples TypeScript coding standard that you must follow.

If you Find below error, add return true at main async function.

typescript error promise contructor
typescript error promise contructor

Besides, you can use TypeScript linter @ tslint (that was set up early) to fix any coding that doesn’t follow TypeScript standard. TypeScript standard is more strict vs JavaScript.

Example of tslint verbose message:

typescript tslint
typescript tslint

Run Unit Test

I use mocha to do unit test.

At package.json, add new script command

Example if you want to run one individual unit test.

If you found Error Cannot find module ‘ts-node/register’

Solution: save ts-node locally as develepment dependency.

Run TypeScript Application

At the terminal or console, type

Conclusion

Even though it takes time to convert from babel javascript into typescript but in the long run it is easier to understand the code and easier to maintain the code.

Besides, you just need to install ts-node and its linter is very good in displaying possible errors.

Benefits of using TypeScript

  • Easy debugging – Typescript shows directly line that throws an error
  • Strong type – any mismatch of variable will be highlighted by ts-lint
  • Less transpilation time – no need to compile like babel. If you have lots of .js files, it takes time to transpile it
  • Support better object oriented – it supports abstract, protected, private methods and variables.