Wednesday, June 01, 2022

Setting up Tizen App Development Environment - All about Installation, Emulator, Remote Watch Device Setup - Part 1

Using and building applications for Android Wearables has always been a dream for me since 2015. Unfortunately, the cost and access to such watches 5 years back made them impossible to explore and debug in real-time. Luckily, around 2021 I got my first Samsung Wearable Watch 4 model in Canada 🍁 with my employer's wellness benefits. However, I used them to track calories burnt, alarms, & alerts. Samsung Health is one of my favorite applications, which creates a competitive environment to challenge people online.

Setting up Tizen Development Environment - All about Installation, Emulator, Remote Watch Device Setup

After a while, I was curious about Samsung App development and started reading through docs and wiki to learn the basics quickly. Fortunately, Tizen App development is similar to Android app development with its own IDE interface. Let's explore them one by one to set up the environment for building a stock ticker application on a watch in a series of a blog posts.

Setting up Tizen App Development Environment - All about Installation, Emulator, Remote Watch Device Setup

Requirements:

- Preferably 8 Gb RAM machine comparing Android Studio, which requires tons of RAM.
- < 5 Gb of Storage
- Samsung Watch to have live debugging enabled. (optional)
- Virtualization is enabled on the laptop to run the emulator.

Installation:

Head over to the Tizen site to grab the IDE application and make sure to install them.
  • Install Watch Development SDK 3+
  • Mobile SDK is optional
  • From extras > choose Certificate Manager Addon
Install the relevant SDK to have them offline to build quickly and deploy.

Certificate Profile Manager:

Make sure to create your own signing certificate by choosing "Samsung" as your primary way. This has been discussed in Stackoverflow as none of the developer sites talks about the issue.

- Create a new certificate and sign in to your Samsung account to accept the terms.

Setting up Tizen App Development Environment - All about Installation, Emulator, Remote Watch Device Setup

Here is the complete step-by-step way to create and save the certificate profile.

Emulator and Watch Setup:

Now that we have successfully set the Tizen SDK with signing certificates, We'll next pivot to develop a sample hello world app that successfully deploys on both emulator and actual watch device in less than 10 minutes. And, that will be covered in the next blog post.

Until then, stay tuned. For bugs/hugs feel free to comment below. Share is care.

Tuesday, May 31, 2022

Odometer.js Animated Number Counter From Zero To Value - JavaScript Animation Part 2

The last time when I wrote Animated Number Counter From Zero To Value post around 2014, there was a substantial unexpected appreciation for this post as it was one of the first blog posts describing the methodology to animate numbers. However, It lacks a few formating and configurations for modern currency usage, number formatting in finance, and other sectors. So, this time I had to either add them as a feature or find some great library to do that. Fortunately, Hubspot (NYSE: HUBS) has open-sourced one of its implementation similar to an animated number counter from zero to value. I'm explaining the odometer.js library in this blog post with a small demo.

Odometer.js Animated Number Counter From Zero To Value - JavaScript Animation Part 2

Install

In the traditional way, contrary to npm install nowadays just include script tag and CSS stylesheet import for theme support.

<link rel="stylesheet" href="http://github.hubspot.com/odometer/themes/odometer-theme-default.css" />

<script src="http://github.hubspot.com/odometer/odometer.js"></script>


Animated Number Counter from Zero to Value

As simple as JQuery API, this time find the reference in the DOM and set up a few configurations to start the animation rolling.

var odometerRef = document.querySelector(".odometer");

od = new Odometer({
  el: odometerRef,
  value: 0,   // initial value
  format: "(,ddd)",
  theme: "default"
});

This time we have theme and format support to customize the numbers displayed in the DOM. Feel free to play with the configuration and themes listed here

Finally, time to update the values:

setInterval(function () {
  qty = qty + 15000;
  odometer.innerHTML = qty++;
}, 3000);

to simulate the value updation, I have utilized setInterval from core javascript to run the function on a defined interval to update the odometer value. 

Demo:


Whenever there is a change in the value, the odometer observes the change and reflects with ease animation. Thus, we have more control now and with a lot of formating and theming options. Imagine building a Stock ticker with an odometer with fluctuation in prices, and a Gasoline meter which odometer.js comes in handy with a few API calls.

Kudos to the Hubspot team πŸ’—and the fantastic CRM product they have built.

That's all for now, meet you soon in the next blog post. Bugs & Hugs, feel free to comment below. Share is care.

Tuesday, January 04, 2022

LRU Cache Implementation LeetCode Solution

Idea

To implement an LRU Cache data structure to store and retrieve data in constant time i.e., O(1). However, We'll have to look for an existing data structure that can perform both store and retrieval processes in almost constant time. HashMap or Hashing generally can help here to efficiently store and retrieve them but with a caveat of not storing them in the least recently used order.

If you're new to LRU Cache, I would suggest you check out this video first.



Explanation

Before jumping into the code snippet, The general idea behind this implementation will require DoublyLinkedList and HashMap internally to make this magic happen.

1. DoublyLinkedList is capable of managing the usage order in almost constant time.

    - Move to Head

    - Remove Object

    - Add Object 

2. HashMap is capable of serving the get and putting a request in almost constant time.

Why not merge them and form an LRU data structure.

class LRUCache {

    class DoublyLinkedListNode {
        int key;
        int value;
        DoublyLinkedListNode previous;
        DoublyLinkedListNode next;
    }
   
    private void addNode(DoublyLinkedListNode node) {
        node.previous = head;
        node.next = head.next;
       
        head.next.previous = node;
        head.next = node;
    }
   
    private void removeNode(DoublyLinkedListNode node) {
        DoublyLinkedListNode previousNode = node.previous;
        DoublyLinkedListNode nextNode = node.next;
       
        previousNode.next = nextNode;
        nextNode.previous = previousNode;
    }
   
    private void moveToHead(DoublyLinkedListNode node) {
        removeNode(node);
        addNode(node);
    }
   
    private DoublyLinkedListNode popTail() {
        DoublyLinkedListNode node = tail.previous;
        removeNode(node);
        return node;
    }
   
    private Map<Integer, DoublyLinkedListNode> cache = new HashMap<>();
    private DoublyLinkedListNode head, tail;
    private int capacity;
    private int size;

    public LRUCache(int capacity) {
        this.size = 0;
        this.capacity = capacity;
       
        head = new DoublyLinkedListNode();
        tail = new DoublyLinkedListNode();
       
        head.next = tail;
        tail.previous = head;
    }
   
    public int get(int key) {
        DoublyLinkedListNode cacheNode = cache.get(key);
       
        if(cacheNode == null) return -1;
       
        moveToHead(cacheNode);
       
        return cacheNode.value;
    }
   
    public void put(int key, int value) {
        DoublyLinkedListNode cacheNode = cache.get(key);
       
        if(cacheNode == null) {
            DoublyLinkedListNode newNode = new DoublyLinkedListNode();
            newNode.value = value;
            newNode.key = key;
           
            addNode(newNode);
            cache.put(key, newNode);
           
            ++size;
           
            if(size > capacity) {
                DoublyLinkedListNode lruNode = popTail();
                cache.remove(lruNode.key);
                --size;
            }
        } else {
            cacheNode.value = value;
            moveToHead(cacheNode);
        }
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */