<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by S.j. Sakib on Medium]]></title>
        <description><![CDATA[Stories by S.j. Sakib on Medium]]></description>
        <link>https://medium.com/@sjsakib?source=rss-13ad3a000340------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*3E3BAiZ8VWW430aW.</url>
            <title>Stories by S.j. Sakib on Medium</title>
            <link>https://medium.com/@sjsakib?source=rss-13ad3a000340------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 02:21:11 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@sjsakib/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Exploring emoji encodings]]></title>
            <link>https://medium.com/@sjsakib/exploring-emoji-encodings-7e80e9417877?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/7e80e9417877</guid>
            <category><![CDATA[string]]></category>
            <category><![CDATA[encoding]]></category>
            <category><![CDATA[emoji]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Wed, 22 Jan 2025 19:09:09 GMT</pubDate>
            <atom:updated>2025-01-22T19:18:41.434Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i8Eiuc9JT9TWeF-hBt0BGw@2x.png" /></figure><p>Have you ever tried to covert a string with emojis to bytes?</p><pre>text = &#39;Hi 🙋🏽‍♂️&#39;<br><br>print(bytes(text, &#39;utf-8&#39;))</pre><pre>b&#39;Hi \xf0\x9f\x99\x8b\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f&#39;</pre><p>And wonder TH are those \x thingies and how do they even translates back to emojis?</p><p>Diving deep, you will find it takes five unicode characters to represent this single emoji.</p><pre>emoji = &#39;🙋🏽‍♂️&#39;<br>print(&quot;Length: &quot;, len(emoji))<br>for c in emoji:<br>    code = ord(c)<br>    print(&quot;{}\t{}\t{}&quot;.format(code, hex(code), c))</pre><pre>Length:  5<br>128587	0x1f64b	🙋<br>127997	0x1f3fd	🏽<br>8205	0x200d	‍<br>9794	0x2642	♂<br>65039	0xfe0f	️</pre><p>First we have the base emoji: person raising hand 🙋 128587 or 0x1f64b in hexadecimal. Often represented as U+1F64B</p><p>Then we have the skin tone modifier: light skin tone 127997</p><p>If you add these two, you will get a gender neutral person with this skin tone raising hand.</p><pre>print(chr(128587) + chr(127997))</pre><pre>🙋🏽</pre><p>The second last one represents a male symbol, and the last one is called Variation Selector-16 (VS16), which indicates the previous character should be displayed as an emoji, rather than a symbol.</p><p>There are many characters can be displayed either as symbol or emoji.</p><pre>heart_symbol= &#39;♥&#39;<br>print(heart_symbol)<br>print(heart_symbol + chr(65039))</pre><pre>♥<br>♥️</pre><p>Note: if the system or the renderer doesn’t support that emoji, it might be rendered as a symbol. In that case, copy the output and paste it into a different text editor or browser to see the difference.</p><p>So, the first two and lat two represents two separate emojis. The middle character is called a Zero Width Joiner (ZWJ), which is used to combine two or more emojis.</p><pre>woman = &#39;👩&#39;<br>laptop = &#39;💻&#39;<br>print(woman + chr(8205) + laptop)</pre><pre>👩‍💻</pre><p>Of course, the system or font has to support these combinations, otherwise it will be rendered just separate.</p><pre>man = &#39;👨&#39;<br>toilet = &#39;🚽&#39;<br><br>print(man + chr(8205) + toilet)</pre><pre>👨‍🚽</pre><p>Now let’s see how each unicode characters in general can be represented as bytes in the utf-8 encoding.</p><p>Let’s consider the character character U+1F64B.</p><p>First we have to determine how many bytes will be required to store this, according to the range of the character. We could store this number itself with just three bytes, but then there would be no way to decode it back to one single character. So this pattern is used instead: (<a href="https://en.wikipedia.org/wiki/UTF-8#Description">why this?</a>)</p><p>11110xxx 10xxxxxx 10xxxxxx 10xxxxxx</p><p>Now lets put the bits of the number 0x1f64b in this pattern. Lets first convert it to binary.</p><pre>print(bin(0x1F64B))</pre><pre>0b11111011001001011</pre><p>The pattern has 21 bits, so let’s add 0s at start to match</p><p>000011111011001001011 000 011111 011001 001011</p><p>putting in the pattern: 11110000 10011111 10011001 10001011</p><p>Now, what are the hexadecimal of these bytes?</p><pre>print(list(map(hex, [0b11110000, 0b10011111, 0b10011001, 0b10001011])))</pre><pre>[&#39;0xf0&#39;, &#39;0x9f&#39;, &#39;0x99&#39;, &#39;0x8b&#39;]</pre><p>Notice that these matches with the first 4 thingies we wanted to understand. Now you know what they mean.</p><p>Find the notebook here: <a href="https://github.com/sjsakib/emoji-encoding/">https://github.com/sjsakib/emoji-encoding/</a></p><p>Leave a star if you enjoyed.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7e80e9417877" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Making your own NestJS on top of express under 180 lines]]></title>
            <link>https://medium.com/@sjsakib/making-your-own-nestjs-73991d125be3?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/73991d125be3</guid>
            <category><![CDATA[nestjs]]></category>
            <category><![CDATA[expressjs]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[typescript]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Fri, 04 Aug 2023 16:08:55 GMT</pubDate>
            <atom:updated>2023-08-04T16:09:43.773Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CPESWtVEZD84c7GJPzrgPQ.png" /></figure><p>It can be a little overwhelming when using <a href="https://nestjs.com/">NestJS </a>for the first time. Let’s try to understand how some of it’s components work.</p><h3>Before you start</h3><p>I am assuming that you are familiar with NestJS and the features it provides. Most of the features that feels like black magic is achieved with <a href="https://www.typescriptlang.org/docs/handbook/decorators.html">decorators</a> and <a href="https://github.com/rbuckton/reflect-metadata">experimental metadata API</a>. Make sure you have basic understanding of these.</p><p>I’ve set up <a href="https://github.com/sjsakib/own-nestjs">this repository</a> with necessary config to run the working snippets I am about to share. You can put them in the <a href="https://github.com/sjsakib/own-nestjs/blob/main/playground.ts">playground.ts</a> file and run them with the command npm run playground. I highly recommend running, changing and playing around with the snippets.</p><h3>Defining routes</h3><p>The key here is that, decorators can attach metadata to classes and methods, and those metadata can be accessed later on runtime. Let’s dive right in.</p><pre>import &#39;reflect-metadata&#39;;<br><br>const PATH_KEY = Symbol(&#39;path&#39;);<br>const HTTP_METHOD_KEY = Symbol(&#39;method&#39;);<br><br>/**<br> * Post is a decorator factory that takes a path and returns a decorator.<br> * That decorator attaches the path and the HTTP method post to the class method it is applied to.<br> **/<br>function Post(path: string) {<br>  return function (target: any, key: string) {<br>    Reflect.defineMetadata(PATH_KEY, path, target, key);<br>    Reflect.defineMetadata(HTTP_METHOD_KEY, &#39;post&#39;, target, key);<br>  };<br>}<br>/* 👆 these are codes that the framework might provide */<br><br>/* So user can write something like this */<br>class AuthRoute {<br>  @Post(&#39;/login&#39;)<br>  async login() {<br>    return &#39;login success&#39;;<br>  }<br>}<br><br>/* Then the framework can use the class to create the actual routes */<br>function createApp(ControllerCls: any) {<br>  // first get all the properties of that class<br>  const properties = Object.getOwnPropertyNames(ControllerCls.prototype);<br>  properties<br>    .filter(<br>      (<br>        method // keep the ones that as HTTP method metadata<br>      ) =&gt; Reflect.hasOwnMetadata(HTTP_METHOD_KEY, ControllerCls.prototype, method)<br>    )<br>    .forEach(method =&gt; {<br>      const path = Reflect.getMetadata(PATH_KEY, ControllerCls.prototype, method);<br>      const httpMethod = Reflect.getMetadata(<br>        HTTP_METHOD_KEY,<br>        ControllerCls.prototype,<br>        method<br>      );<br>      console.log(`Mapping: ${httpMethod.toUpperCase()} ${path}`);<br>      // now that we have access to the method name and path at runtime,<br>      // these could be attached to an express app<br>    });<br>}<br><br>createApp(AuthRoute);</pre><p>Note that, using <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol">symbol</a> is not mandatory here, could just use plain strings for the keys.</p><h3>Dependency injection</h3><p>The basic idea of dependency injection is that instead of instantiating the dependencies of a class in the constructor, you pass the dependencies to the constructor. The mystical thing that NestJS does here is, you can define the dependencies in the constructor with shorthand express like constructor(private service: Service) and NestJS will do the instantiating and pass it down to the constructor for you. Let&#39;s see how something like that is possible.</p><p>Again metadata API comes into play. The parameters of a constructors is available with the design:paramtypes key in the metadata. The catch is that, the class has to be decorated with at least one decorator. Otherwise typescript will not record the parameter data while transpiling to runnable javascript. This is where the @Injectable() decorator comes into play. You might have noticed that NestJS will have you decorate the controllers with the Controller() decorator even when no controller prefix is required. This is because all classes need to be decorated with at least one decorator in order for them to be instantiated with correct params.</p><pre>import &#39;reflect-metadata&#39;;<br><br>function Injectable() {<br>  return function (target: any) {}; // it doesn&#39;t have to do anything<br>}<br><br>class UserRepository {<br>  async findUser() {<br>    return &#39;user exists&#39;;<br>  }<br>}<br><br>@Injectable()<br>class AuthService {<br>  constructor(private readonly userRepo: UserRepository) {}<br>  login() {<br>    return this.userRepo.findUser();<br>  }<br>}<br><br>function instantiate(ProviderCls: any) {<br>  const params = Reflect.getMetadata(&#39;design:paramtypes&#39;, ProviderCls).map(<br>    DependencyCls =&gt; new DependencyCls()<br>  );<br><br>  const provider = new ProviderCls(...params);<br><br>  provider.login().then(console.log);<br>}<br><br>instantiate(AuthService);</pre><p>Note that, it didn’t need to be a decorator factory, since it is not taking params. We could define it like function Injectable(target: any) {} then it could be used like @Injectable, without the braces. Just making it look like the other decorators.</p><h3>What about passing data down to the route handlers?</h3><p>With a similar technique, parameters can be decorated to indicate what kind of data is needed in that parameter, and then the framework can pass down the appropriate data, taking form the underlying platform.</p><pre>import &#39;reflect-metadata&#39;;<br><br>const HTTP_METHOD_KEY = Symbol(&#39;method&#39;);<br>const PATH_KEY = Symbol(&#39;path&#39;);<br>const PARAMS_META_KEY = Symbol(&#39;paramsMeta&#39;);<br><br>// just like the first snippet<br>function Get(path: string) {<br>  return function (target: any, key: string) {<br>    Reflect.defineMetadata(PATH_KEY, path, target, key);<br>    Reflect.defineMetadata(HTTP_METHOD_KEY, &#39;get&#39;, target, key);<br>  };<br>}<br><br>// decorator to indicate that data is required from route parameter<br>export function Param(key: string) {<br>  return function (target: any, methodName: string, index: number) {<br>    const paramsMeta = Reflect.getMetadata(PARAMS_META_KEY, target, methodName) ?? {};<br>    paramsMeta[index] = { key, type: &#39;route_param&#39; };<br>    Reflect.defineMetadata(PARAMS_META_KEY, paramsMeta, target, methodName);<br>  };<br>}<br><br>class AuthRoute {<br>  @Get(&#39;/profile/:id&#39;)<br>  async profile(@Param(&#39;id&#39;) id: string) {<br>    return `user: ${id}`;<br>  }<br>}<br><br>function createApp(ControllerCls: any) {<br>  Object.getOwnPropertyNames(ControllerCls.prototype)<br>    .filter(method =&gt;<br>      Reflect.hasOwnMetadata(HTTP_METHOD_KEY, ControllerCls.prototype, method)<br>    )<br>    .forEach(method =&gt; {<br>      const PARAM_DATA = { id: &#39;123&#39; }; // could get from req.params<br><br>      const paramsMeta =<br>        Reflect.getMetadata(PARAMS_META_KEY, ControllerCls.prototype, method) ?? {};<br><br>      const paramsToPass = Reflect.getMetadata(<br>        &#39;design:paramtypes&#39;,<br>        ControllerCls.prototype,<br>        method<br>      ).map((_, index) =&gt; {<br>        const { key, type } = paramsMeta[index];<br>        if (type === &#39;route_param&#39;) return PARAM_DATA[key];<br>        return null;<br>      });<br>      ControllerCls.prototype[method](...paramsToPass).then(console.log);<br>    });<br>}<br><br>createApp(AuthRoute);</pre><h3>Putting it all together</h3><p>I’ve tried to keep the snippets as short and easy to understand as possible. You can see the lib.ts where I&#39;ve put them together with actual express. And in the index.ts there is a working web app using this &#39;framework&#39;. Their you have it, a nestjs-like framework on top of express under 180 lines of code. This is how it would look like in action:</p><pre>import {<br>  Body,<br>  Controller,<br>  Get,<br>  Injectable,<br>  Module,<br>  Param,<br>  Post,<br>  createApp,<br>} from &quot;./lib&quot;;<br><br>class LoginDto {<br>  username: string;<br>  password: string;<br>}<br><br>@Injectable()<br>class UserRepository {<br>  async findOne(id: string) {<br>    return { userId: id };<br>  }<br>}<br><br>@Injectable()<br>class AuthService {<br>  constructor(private readonly userRepository: UserRepository) {}<br>  async login({ username }: LoginDto) {<br>    return `login successful for ${username}`;<br>  }<br>  async findUser(id: string) {<br>    return this.userRepository.findOne(id);<br>  }<br>}<br><br>@Controller(&#39;auth&#39;)<br>class AuthController {<br>  constructor(private readonly authService: AuthService) {}<br>  @Post(&#39;/login&#39;)<br>  login(@Body() loginData: LoginDto) {<br>    console.log({ loginData });<br>    return this.authService.login(loginData);<br>  }<br>  @Get(&#39;/profile/:id&#39;)<br>  async profile(@Param(&#39;id&#39;) id: string) {<br>    const user = await this.authService.findUser(id);<br>    return `user: ${user.userId}`;<br>  }<br>}<br><br>@Module({<br>  controllers: [AuthController],<br>  providers: [AuthService],<br>})<br>class AppModule {}<br><br><br>const app = createApp(AppModule);<br>app.listen(3001, () =&gt; {<br>  console.log(&#39;listening on port 3001&#39;);<br>});</pre><p>It doesn’t handle a lot of things of course, but it is a good starting point to understand how a framework like NestJS works under the hood.</p><p>Thanks for reading. <a href="https://github.com/sjsakib/own-nestjs">Leave a star</a> if you liked it.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=73991d125be3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[অপারেটিং সিস্টেম কি করে? কিভাবে করে? —  প্রথম খন্ড]]></title>
            <link>https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/%E0%A6%85%E0%A6%AA%E0%A6%BE%E0%A6%B0%E0%A7%87%E0%A6%9F%E0%A6%BF%E0%A6%82-%E0%A6%B8%E0%A6%BF%E0%A6%B8%E0%A7%8D%E0%A6%9F%E0%A7%87%E0%A6%AE-%E0%A6%95%E0%A6%BF-%E0%A6%95%E0%A6%B0%E0%A7%87-%E0%A6%95%E0%A6%BF%E0%A6%AD%E0%A6%BE%E0%A6%AC%E0%A7%87-%E0%A6%95%E0%A6%B0%E0%A7%87-%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A6%A5%E0%A6%AE-%E0%A6%96%E0%A6%A8%E0%A7%8D%E0%A6%A1-d5f6a910bacb?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/d5f6a910bacb</guid>
            <category><![CDATA[bangla]]></category>
            <category><![CDATA[operating-systems]]></category>
            <category><![CDATA[computer-science]]></category>
            <category><![CDATA[অপারেটিং-সিস্টেম]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Mon, 27 Apr 2020 13:46:03 GMT</pubDate>
            <atom:updated>2020-04-27T13:46:03.004Z</atom:updated>
            <content:encoded><![CDATA[<h3>অপারেটিং সিস্টেম কী করে? কিভাবে করে? — প্রথম খন্ড</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j03L7Am5bOmHEOLiW9gjUA.png" /></figure><p>নিজে নিজে টুকটাক কম্পিউটার সায়েন্স শেখার পরিকল্পনার অংশ হিসেবে <a href="http://www.ostep.org/">Operating Systems: Three Easy Pieces</a> বইটি পড়া শুরু করলাম। এইমাত্র প্রথম অংশটি পড়ে শেষ করলাম (তিন পিসের এক পিস)। শেখাটা পাকাপোক্ত করার জন্য চুম্বকাংশগুলো লিখে ফেলার চেষ্টা করব।</p><h4>আপারেটিং সিস্টেমের কাজ কী?</h4><p>একটি অপারেটিং সিস্টেমের মূল কাজ হল একটি কম্পিউটারে চলা প্রোগ্রামগুলোকে ম্যানেজ করা। একেকটি প্রোগ্রামের বেশ কিছু রিসোর্স লাগে। যেমন প্রসেসর, মেমরি (RAM), স্টোরেজ, নেটওয়ার্ক ইত্যাদি। অপারেটিং সিস্টেমের একটি কাজ হল এই রিসোর্সগুলোকে সহজে ব্যবহারযোগ্য করে উপস্থাপন করা। যাতে রিসোর্সগুলো কিভাবে কাজ করে, available আছে কিনা ইত্যাদি নিয়ে সাধারণ প্রোগ্রমারের মাথা ঘামাতে না হয়। এই প্রক্রিয়াটিকে বলা হয় ভার্চুয়ালইজেশন।</p><p>আরেকটি গুরুত্বপূর্ণ কাজ হল এই রিসোর্সগুলোকে ভিন্ন ভিন্ন প্রোগ্রামের মধ্যে বন্টন করে দেয়া। যাতে এক প্রোগ্রাম অন্য প্রেগ্রামের এক্সিকিউশনে কোন বিঘ্ন ঘটাতে না পারে (ইচ্ছাকৃতভাবে কিংবা ভুলবশত)। একটি মর্ডান ডেস্কটপ অপারেটিং সিস্টেমের হয়ত আরো অনেক কিছুই করতে হয়। কিন্তু এগুলোই অপারেটিং সিস্টেমের মূল কাজ।</p><h4>প্রসেস</h4><p>প্রসেস হচ্ছে একটি চলমান প্রোগ্রাম। স্টোরেজে সংরক্ষিত কিছু ইন্সট্রাকশনকে আমরা বলি একটি প্রোগ্রাম। সেটি যখন মেশিনে চলতে শুরু করে, তখন হয়ে যায় একটি প্রসেস। একটি প্রসেসের সাথে বেশ কিছু জিনিস জড়িত থাকে। যেমনঃ সিপিইউ তে একটি রেজিস্টারে সংরক্ষিত সংখ্যা নির্দেশ করে, এই মুহূর্তে প্রসেসটির কত নাম্বার ইন্সট্রাকশন এক্সিকিউট হচ্ছে? এই রেজিস্টারটিকে বলে PC (Program Counter). এছাড়া আরো কিছু রেজিস্টার একটি প্রসেসের সাথে সংশ্লিষ্ট থাকে, যা প্রসেসটি হিসাব নিকাশের কাজে ব্যবহার করে থাকে।</p><p>তারপরে আছে প্রসেসের সাথে সম্পর্কিত মেমরি যা প্রসেসটি এক্সেস করতে পারে। এই মেমরির এক অংশে থাকে স্বয়ং প্রসেসটির কোড। তারপরে একটি স্ট্যাকে থাকে ডিক্লেয়ার করা ভ্যারিয়েবলগুলো। তারপরে থাকে হিপ যা ম্যানুয়ালি অ্যালোকেট করা মেমরি ধারণ করে।</p><h4>অপারেশন মোড</h4><p>কোন একটি প্রসেসকে সিস্টেমে সবকিছু করতে দেয়া যায় না। যেমন সব প্রসেসকে ইচ্ছামত মেমরি দখল করার, বা স্টোরেজ এক্সেস করার অধিকার দেয়া যায় না। দিলে প্রথমত সেটা অন্যান্য প্রোগ্রামের জন্য সমস্যা হতে পারে। অথবা প্রোগ্রামার যদি সেই রিসোর্স ভুলভাবে ব্যবহার করে তাহলে পুরো সিস্টেম ক্রাশ করতে পারে। কোনভাবে সীমিত আকারে প্রোগ্রামগুলোকে রিসোর্সগুলো ব্যবহার করার সুয‌োগ করে দিতে হবে।</p><p>এই সমস্যাটি সমাধান করতে সিপিইউতে একটি বিশেষ মোড ব্যবহার করা হয়। user mode। এই মোডে একটি প্রসেস কোন নিষিদ্ধ কাজ (যেমন I/O অপারেশন) করতে পারে না। যদি করে তাহলে সিপিইউ একটি এক্সেপশন রেইজ করবে। আর OS সেই আসামী প্রসেসটিকে মেরে ফেলবে!</p><p>প্রসেসগুলো system call এর মাধ্যমে নিষিদ্ধ কাজগুলো করতে পারবে। system call করার জন্য প্রসেসকে একটি বিশেষ trap instruction একক্সিকিউট করতে হবে। এই ইন্সট্রাকশন এক্সিকিউট করলে প্রসেসর লাফ দিয়ে kernel এর ভেতরে চলে যাবে আর মুড বদলে হয়ে যাবে kernel mode। এসময় প্রসেসটির PC এবং CPU তে থাকা অন্যান্য তথ্য প্রতি প্রসেসের জন্য বরাদ্দ একটি kernel stack -এ পুশ করা হবে।</p><p>Kernel মোডে CPU কোন বাধা ছাড়া সব ধরণের ইন্সট্রাকশন এক্সিকিউ করতে পারে। সিস্টেম তখন দেখতে পারবে সেই নিষিদ্ধ কাজটি অনুমোদিত কিনা বা করলে কোন সমস্যা হবে কিনা। সব ঠিক থাকলে সিস্টেম কাজটি করে আবার একটি বিশেষ return-from-trap ইন্সট্রাকশন এক্সিকিউট করবে। তখন ম‌োড আবার user mode এ ফিরে যাবে এবং kernel stack পপ হবে। প্রসেসটি স্বাভাবিকভাবে চলতে থাকবে।</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FLqBucbYGCBMEZWyk8z%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fgiphy.com%2Fgifs%2Fcomputer-operating-system-LqBucbYGCBMEZWyk8z&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FLqBucbYGCBMEZWyk8z%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="444" frameborder="0" scrolling="no"><a href="https://medium.com/media/155f05d7c3a0a8f2c1f521dbc28e53f3/href">https://medium.com/media/155f05d7c3a0a8f2c1f521dbc28e53f3/href</a></iframe><p>এখন kernel এর কোথায় কী কোড আছে সেটা সেটা ইউজার প্রসেসকে জানিয়ে দিলে বিভিন্ন রকমের নিরাপত্তাজনিত সমস্যা তৈরী হবে। তাই boot এর সময় একটি ট্র্যাপ টেবিল সেট আপ করে CPU কে জানিয়ে রাখা হয়, যেখানে সিস্টেম অপারেশনগুলোর অ্যাড্রেস একটি নাম্বার দিয়ে সংরক্ষণ করা থাকে। ইউজার প্রোগ্রাম যখন কোন একটি সিস্টেম অপারেশন করতে চাইবে, তখন এই নাম্বারটি ধরে কল করবে। CPU তখন বুঝতে পারবে এক্সিকিউশন কোথায় লাফ দিবে। C প্রোগ্রামিং ল্যাঙ্গুয়েজে আমরা এমন অনেক সিস্টেম কল দেখতে পাই, যেমন- open , read , write , fork , connect ইত্যাদি।</p><h4>টাইম শেয়ারিং</h4><p>সিপিইউ ভার্চুয়ালইজেশনের একটি অন্যতম ধাপ হল একটি সিপিইউ তে এক সাথে একাধিক প্রোগ্রাম চালানোর একটি ব্যবস্থা করা। (যদিও আধুনকি কম্পিউটারগুলোতে একাধিক প্রসেসর থাকে। কিন্তু একসাথে এর চেয়ে অনেক বেশি প্রোগ্রাম চালাতে হয়)। সমাধান খুবই সিম্পল! একটি প্রোগ্রাম কিছুক্ষণ চালিয়ে তারপর সেটা বন্ধ রেখে অন্য একটি প্রোগ্রাম চালানো শুরু করতে হবে, তারপর অন্য একটি। এই কৌশল <strong>টাইম শেয়ারিং</strong> হিসেবে পরিচিত।</p><h4>ইন্টারাপ্ট</h4><p>একটি বিষয় খেয়াল করতে হবে যে OS যদি অন্যান্য প্রসেস নিয়ন্ত্রণ করতে চায় তাহলে OS এর নিজেরই কিন্তু CPU এর দরকার পড়বে, মানে OS এর কোড CPU তে একক্সিকিউট হতে হবে। এখন মনে করুন একটি প্রসেস সিপিইউতে চলছে। সিপিইউ ঐ প্রোগ্রামের ইন্সট্রাকশনগুলো একটি একটি করে এক্সিকিউট করে যাচ্ছে। এখন যদি এভাবে চলতেই থাকে তাহলে OS নিজে CPU তে ফিরে আসবে কী করে? আর সেই প্রসেস বা অন্য প্রসেসগুলোকে নিয়ন্ত্রণ ই বা করবে কিভাবে? আর প্রসেসটিতে যদি কোন কারণে infinity loop সৃষ্টি হয় তাহলে? পাওয়ার কর্ড খুলা ছাড়া উপায় কী?</p><p>এই সমস্যা সমাধান করার সময় সিপিইউতে একটি মেকানিজম থাকে। প্রোগ্রাম চালানোর সময় কিছুক্ষণ পর পর সিপিইউ একটি interrupt রেইজ করে। এতে করে প্রসসেসটি সাময়িকভাবে থেমে যায় ও এক্সিকিউশন কার্নেলে চলে যায়। ইন্টারাপ্টে এক্সিকিউশন কার্নেলের কোথায় যাবে সেটা আগে থেকেই ট্রাপ টেবিলে বলে দেয়া থাকে। এভাবে OS নিয়ন্ত্রণ ফিরে পায় ও প্রয়োজনে অন্য প্রসেসে সুইচ করতে পারে।</p><h4>কন্টেক্সট সুইচ</h4><p>টাইম শেয়ারিং ইম্প্লিমেন্ট করার জন্য অবশ্যই এক প্রসেস থেকে সুইচ করে অন্য প্রসেস চালানোর সক্ষমতা থাকবে হবে। এজন্য OS সাধারণত একটি লো লেভেল ইন্সট্রাকশন এক্সিকিউট করে, যা প্রসেসটির PC এবং অন্য রেজিস্টারগুলো কপি করে মেমরিতে কোথাও রেখে দেয়। আর যে প্রসেসে সুইচ করা হচ্ছে সেই প্রসেসের PC আর অন্য রেজিস্টরগুলো সিপিইউতে লোড করে নেয়। এই প্রক্রিয়াটিকে বলা হয় কন্টেক্সট সুইচ।</p><h4>শিডিউলিং</h4><p>তাহলে এখন প্রসেসগুলোকে নিয়ন্ত্রণে রেখে সীমিত প্রিভিলেজ দিয়ে চালানোর ব্যবস্থা হল। কন্টেক্সট সুইচেরও ব্যবস্থা হল। এখন সিদ্ধান্ত নিতে হবে কোন প্রসেস বা প্রসেসগুলোকে আগে চলতে দেয়া হবে হবে আর কোনগুলোকে পরে। এই সিদ্ধান্ত নেয়ার জন্য সব অপারেটিং সিস্টেমে একটি শিডিউলার অংশ থাকে। একটি শিডিউলারের উদ্দেশ্যগুলো হল:</p><ul><li>কাজ থাকতেও সিপিইউ যাতে কখনোই বসে না থাকে</li><li>সিস্টেমে থাকা সবগুলো প্রসেস যত তাড়াতাড়ি সম্ভব শেষ করা</li><li>আলাদাভাবে প্রত্যেকটি প্রসেস নূন্যতম সময়ে শেষ করা। মানে সবগুলো প্রসেস তাড়াতাড়ি শেষ করতে গিয়ে কোন একটি প্রসেস আটকে থেকে অনেক বেশি সময় লেগে গেল, এমন যাতে না হয়</li><li>প্রথমবার রেসপন্স করতে বা আউটপুট জেনারেট করতে একটি প্রসেসের যে সময় লাগবে সেটা সর্বনিম্ন করা</li><li>একেকটি প্রসেসের এক্সিকিউট হওয়ার জন্য যে সময় অপেক্ষা করবে সেটা সর্বনিম্ন করা</li></ul><p>একটি সহজ সমাধান হতে পারে, যে প্রসেসটি আগে আসবে সেটি আগে চালিয়ে সম্পূর্ণ শেষ করে তারপরে বাকিগুলোতে যাওয়া। এতে সমস্যা হল, কোন একটি প্রোগ্রাম যদি সময় বিবেচনায় অনেক বড় হয় এবং আগে আসে তাহলে সেটা অন্য সব ছোট ছোট প্রোগ্রামকে বসিয়ে রাখবে। এর মধ্যে ইউজার নতুন কোন প্রোগ্রাম চালাতে চাইলে সেটাও বসে থাকবে।</p><p>আরেকটি সমাধান করা যায় এভাবে। প্রত্যেকটি প্রসেস একটি নির্দিষ্ট সময়ের জন্য চালানো, এর মধ্যে এটি শেষ হয়ে গেলে তো গেলই, না হলে এর পরের প্রসেসে চলে যাওয়া। এভাবে সবগুলো প্রসেস ঘুুরে এসে আবার প্রথমটিতে আসা। এই কৌশল <strong>Round Robin (RR)</strong> নামে পরিচিত। এই নির্দিষ্ট সময়ের স্লাইসটিকে অনেকসময় বলা হয়ে থাকে scheduling quantum. এখানে স্লাইসটি যত ছোট করা হবে, রেসপন্স টাইম তত ভাল হবে। কিন্তু অনেক বেশি ছোট হলে আবার সমস্যা। কেননা কন্টেক্সট সুইচ করতে বেশ কিছু সময় লাগে। খুব বেশি বার করলে এতেই সিস্টেমের অনেক সময় চলে যাবে।</p><p>আরেকটি ব্যাপার হল I/O। I/O অপারেশন সাধারণত সিপিইউর বাইরে অনেক সময় নেয়। তাই কোন একটি প্রসেস I/O শুরু করলে CPU বসিয়ে না রেখে অন্য প্রসেসে সুইচ করা একটি ভাল বুদ্ধি। তখন আবার আরেকটি সিদ্ধান্ত নিতে হবে যে ঐ প্রসেসের I/O শেষ হলে সাথে সাথে আবার ঐ প্রসেসে সুইচ করা হবে নাকি অন্যগুলোর রাউন্ড শেষ হলে আবার ঐটাতে আসবে। যদি সাথে সাথে সুইচ না করা হয় তাহলে দেখা যাবে যে প্রসেসগুলোতে I/O বেশি সেগুলো সিপিইউ টাইম খুব কম পাবে। অথচ সেগুলো সাধারণত ইন্টারেক্টিভ ধরণের প্রোগ্রাম যেখানে ইউজার ইনপুট দিয়ে সাথে সাথে আউটপুট পাবার আশা করে। আবার যদি সাথে সাথে সুইচ করা হয় তাহলে একটি প্রসেস চাইলে একটি নির্দিষ্ট সময় পর পর (scheduling quantum শেষ হওয়ার ঠিক আগে) বিনা কারণে একটি ছোট I/O কল করে প্রায় সাথে সাথেই সিপিইউতে ফিরে আসতে পারবে। এভাবে পুরো সময়ই ঐ প্রসেস একা সিপিইউ দখল করে রাখতে পারবে। এমন সুযোগ দিয়ে রাখা সিস্টেমের জন্য ভাল হতে পারে না।</p><h4>মাল্টিলেভেল ফিডব্যাক কিউ (MLFQ)</h4><p>Multilevel Feedback Que একটি জনপ্রিয় শিডিউলার। এতে একাধিক ভিন্ন প্রায়োরিটিসম্পন্ন একাধিক কিউতে প্রসেসগুলো রেখে অনেকটা RR এর মত এক্সিকিউট করা হয়। এতে কিছু বিশেষ কৌশল ব্যবহার করা হয় যাতে প্রসেগুলো বৈশিষ্ট্য/আচরণের উপর ভিত্তি করে সিপিইউ বরাদ্দ পায়। এর কৌশলগুলো কিছুটা এমন:</p><ul><li>প্রথম কিউ-টির প্রায়োরিটি সবচেয়ে বেশি। তারপরেরটির কম। এভবে বিভিন্ন প্রায়োরিটির বেশ কয়েকটি কিউ থাকতে পারে</li><li>সিস্টেমে নতুন কোন প্রসেসে আসলে সেটিকে প্রথম কিউতে ঢুকানো হবে</li><li>সবচেয়ে বেশি প্রয়োটির যে কিউ-টিতে কোন প্রসেস আছে সেটির প্রসেসগুলোকে RR কৌশলে এক্সিকিউট করা হবে। এক্ষেত্রে কোন প্রসেস I/O ইস্যু করলে সেটিকে বন্ধ রাখা হবে। I/O শেষ হলে আবার সাথে সাথে সুউচ করা হবে</li><li>একটি প্রসেস কোন কিউতে টানা একটি scheduling quantum পার করে ফেললে সেটিকে এর নিচের কিউতে নামিয়ে দেয়া হবে। এতে করে নন-ইন্টাঅ্যাক্টিভ লম্বা প্রসেসগুলো সিপিইউ দখল করে রাখতে পারবে না</li><li>কোন প্রসেস I/O ইস্যু করে কতবার থামল সেটি উপেক্ষা করে কোন একটি কিউতে এর scheduling quantum শেষ হয়ে গেলে সেটিকেও নিচের কিউতে নামিয়ে দেয়া হবে। এতে করে কোন প্রসেস চালাকি করে সিপিইউ দখল করে রাখতে পারবে না</li><li>এখন একটি সমস্য হল যদি ছোটখাট প্রসেস সিস্টেমে আসতেই থাকে তাহলে বড় প্রসেসগুলো একেবারেই সিপিইউ পাবে না। আবার কোন প্রসেস প্রথম দিকে কোন ইন্টারঅ্যাকশন ছাড়া শুধু সিপিইউ ব্যবহার করে যদি পরে ইন্টার‍অ্যাক্টিভ হতে চায় তাহলে সেটাও সমস্যা হবে। এজন্য যা করতে হবে তা হল একটি নির্দিষ্ট সময় পর প্রায়োরিটি বুস্ট করে সবগুলো প্রসেসকেই একেবারে সবার প্রথম কিউ-তে তুলে দিতে হবে।</li></ul><p>কোন কোন ইম্প্লিমেন্টেশনে একেক কিউর জন্য একেক আকারের scheduling quantum ব্যবহার করা হয়।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oa7qAsvHFGsn7aDvP17yyg.png" /><figcaption>Rough illustration of MLFQ</figcaption></figure><p>MLFQ শিডিউলিং এর অনেকগুলো সমস্যাই বেশ ভালভাবে সমাধান করে। ইউনিক্সের বিএসডি ডেরিভেটিভগুলোতে এবং খুব সম্ভবত ইউন্ডোজেও এই শিডিউলারটিরই কিছুটা পরিবর্তিত সংস্করণ ব্যবহার করা হয়।</p><p>তবে এর একটি অন্যতম সমস্যা হল এতে অনেকগুলো প্যারামিটার বিদ্যমান। যেমন কয়টি কিউ ব্যবহার করা হবে, scheduling quantum কত হবে, প্রয়োরিটি বুস্ট কতক্ষণ পর পর করতে হবে ইত্যাদি। এগুলো সঠিকভাবে নির্ধারণ করা বেশ কঠিন।</p><h4>কম্প্লিটলি ফেয়ার শিডিউলার (CFS)</h4><p>লিনাক্স কার্নেল বর্তমানে ব্যবহৃত শিডিউলারটি হল Completely Fair Scheduler. নাম থেকে যেমন বুঝা যায়, এটি সব প্রসেসকে সমানভাবে দেখে। প্রত্যেকে প্রসেসের সাথে সংশ্লিষ্ট একটি virtual runtime বা vruntime থাকে। একটি প্রসেস যতক্ষণ চলে এর vruntime সেই অনুসারে বাড়ানো হয়। কোন প্রসেস চালানো হবে সিদ্ধান্ত নেয়ার সময় vruntime ওয়ালা প্রসেসটিকে নেয়া হয়। ব্যাপারটি ইফিশিয়েন্ট করতে প্রসেসগুলোকে একটি রেড ব্ল্যাক ট্রিতে রাখা হয়। CFS এ প্রত্যেকটি প্রসেসের আবার একটি nice মান থাকে। এই মানটি ব্যবহার করে প্রত্যেকটি প্রসেসের জন্য আলাদাভাবে time slice ও vruntime হিসেব করা হয়। এতে করে মানটি একটি প্রসেসের প্রয়োরিটি নির্ধারণ করে। ছোট মান বেশি প্রয়োরিটি নির্দেশ করে। (একটি প্রসেসের নাইস মান বেশি মানে হল প্রসেসটি ভদ্র, বেশি পাত্তা না দিলেও হবে)। লিনাক্সের ‍<a href="http://man7.org/linux/man-pages/man1/top.1.html">top</a> টুলের NI কলামে এই মানটি দেখা যায়। এটি চাইলে ইউজার বা সিস্টেম অ্যাডমিন পরিবর্তন করতে পারে।</p><p>আরো কিছু শিডিউলার হল <a href="https://en.wikipedia.org/wiki/Brain_Fuck_Scheduler">BFS</a>, O(1) শিডিউলার (নামটি প্রসেস খোঁজার টাইম কম্প্লেক্সিটির উপর ভিত্তি করে), O(n) শিডিউলার ইত্যাদি।</p><p>বইটি সম্পূর্ণ ফ্রিতে এখানে পড়া যাবে: <a href="http://www.ostep.org/">http://ostep.org/</a></p><p>আমার হোমওয়ার্কগুলো এখানে আছে: <a href="https://github.com/sjsakib/cs">https://github.com/sjsakib/cs</a>, ছোট করে একটা স্টার দিয়ে আসলে ভাল লাগবে :D</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d5f6a910bacb" width="1" height="1" alt=""><hr><p><a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/%E0%A6%85%E0%A6%AA%E0%A6%BE%E0%A6%B0%E0%A7%87%E0%A6%9F%E0%A6%BF%E0%A6%82-%E0%A6%B8%E0%A6%BF%E0%A6%B8%E0%A7%8D%E0%A6%9F%E0%A7%87%E0%A6%AE-%E0%A6%95%E0%A6%BF-%E0%A6%95%E0%A6%B0%E0%A7%87-%E0%A6%95%E0%A6%BF%E0%A6%AD%E0%A6%BE%E0%A6%AC%E0%A7%87-%E0%A6%95%E0%A6%B0%E0%A7%87-%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A6%A5%E0%A6%AE-%E0%A6%96%E0%A6%A8%E0%A7%8D%E0%A6%A1-d5f6a910bacb">অপারেটিং সিস্টেম কি করে? কিভাবে করে? —  প্রথম খন্ড</a> was originally published in <a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE">প্রোগ্রামিং পাতা</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reverse engineering a netis router to build a mobile app for it]]></title>
            <link>https://medium.com/@sjsakib/reverse-engineering-a-netis-router-to-build-a-mobile-app-for-it-3425790f3530?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/3425790f3530</guid>
            <category><![CDATA[wifi]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[router]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Thu, 29 Aug 2019 14:42:18 GMT</pubDate>
            <atom:updated>2019-08-29T14:42:18.569Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*D8CBQjB6nlqMEq2_5NwWpw.png" /></figure><p>Netis routers are very popular in our country, at least in my town. Probably because of their lower price. But one convenience they don’t come with is a mobile app. So I built one, with react native.</p><h3>How?</h3><p>I noticed that the admin site works through ajax. Inspecting the source revealed that they are mostly using jQuery. First I tried to to read the source to extract an API. But even the very helpful Mandarin comments couldn’t help me understand anything much.</p><p>So what I did is, I headed to the network tab of dev tools. There I could see all the network activities. Only two endpoints. One netcore_set returns all informations of the router, like from SSID, password to address reservation, mac filtering list and all. And there was another netcore_set endpoint do all the stuffs.</p><p>The main two features I wanted to implement was blocking device and setting speed limit on devices. And to set speed limit I had to reserve the IPs, because the routers doesn’t support bandwidth control with mac.</p><p>So what I did was I did those things form the admin site and inspected the requests sent to the server in the router. Took some time to understand what parameter did what. Some of them were pretty weired. Like for sending a list of something say mac they send multiple parameters like mac1, mac2, mac3 instead of using comma separated values or anything. And instead of using different end points they use a flag parameter to determine what a request does. Wish I could see how they implement all these in the backend.</p><p>They rest was pretty easy. I wanted to build it as a PWA. But couldn’t do so for CORS issues. So built it with react-native (expo).</p><p>For now it supports a blocking devices, setting speed limit and changing network name and password. I might add few more features like blocking specific domains in the future.</p><p>It might not work with different models or firmware versions of netis routers. If you happen to be using a netis router, why don’t you give it a try? And if you find it useful, don’t forget to give it a star on GitHub and then to give a rating on Google Play :)</p><ul><li><a href="https://github.com/sjsakib/my-netis">sjsakib/my-netis</a></li><li><a href="https://play.google.com/store/apps/details?id=dev.sakib.mynetis">My Netis - Easily manage your Netis router - Apps on Google Play</a></li></ul><p>If you are using iOS, you can use the app using the Expo client. Download the Expo app from App Store and scan the QR code from <a href="https://expo.io/@sjsakib/my-netis">here</a></p><p><em>Originally published at </em><a href="https://sakib.dev/blog/my-netis/"><em>https://sakib.dev</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3425790f3530" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A* সার্চ]]></title>
            <link>https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/a-%E0%A6%B8%E0%A6%BE%E0%A6%B0%E0%A7%8D%E0%A6%9A-7b74704405de?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/7b74704405de</guid>
            <category><![CDATA[algorithms]]></category>
            <category><![CDATA[bangla]]></category>
            <category><![CDATA[graph]]></category>
            <category><![CDATA[search]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Thu, 30 May 2019 10:13:58 GMT</pubDate>
            <atom:updated>2019-06-06T05:10:13.425Z</atom:updated>
            <content:encoded><![CDATA[<h4>স্লাইডিং পাজল সমাধান: ডিএফএস vs বিএফএস vs A* সার্চ</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/810/1*qDARH7JfK7_ZitGTRnc3AQ.png" /></figure><p>একটি স্লাইডিং পাজলে সাধারণত মোট আটটি স্কয়ার আর একটি খালি জায়গা থাকে। খালি জায়গাটির অবস্থান পরিবর্তন করে পাজলটিকে এলোমেলো করা যায়, আবার সমাধানও করা যায়। আমরা কোড করে এই পাজলটিকে সমাধন করার চেষ্টা করব।</p><p>খালি জয়গা সহ নয়টি স্কয়ারের মোট ৯! = ৩৬২৮৮০ রকম কনফিগারেশন হতে পারে। যার মধ্যে একটি কনফিগারেশন সমাধান। আমাদের কাজ হবে যেকোন এলোমেলো কনফিগারেশন থেকে সেই সমাধান কনফিগারেশনে কিভাবে যেতে হবে বের করা।</p><p>আমরা সমস্যাটিকে একটি গ্রাফ হিসেবে বিবেচনা করব। যেখানে প্রতিটি কনফিগারেশন হল একেকটি নোড। আার ঐ কনফিগারেশন থেকে যে সব কনফিগারেশনে যাওয়া যায় সেগুলো হল ঐ নোডের নেইবার। প্রতিটি নোডকে আমরা ০ থেকে ৯ সংখ্যাগুলোর একটি অ্যারে দিয়ে রিপ্রেজেন্ট করব।</p><p>এখনে ব্যবহার করা অ্যালগরিদমগুলোর মূল প্রক্রিয়া একই। আমরা শুরুর এলোমেলো নোডটি toCheck এ রাখব। আর যে নোডগুলো অলরেডি চেক করা হয়েছে সেগুলো রাখার জন্য checked একটি সেট নেব। তারপর toCheck থেকে একেকটি নোড নিয়ে চেক করতে থাকব। যদি দেখা যায় নোডটি সমাধান নোড তহলে এই নোডে আসার স্টেপগুলোই আমাদের সমাধান। আর যদি না হয় তাহলে ঐ নোডের আশেপাশের নোডগুলো বের করে toCheck এ রাখব (যদি সেটা checked এ না থাকে) এবং checked এ চেক করা নোডটি রেখে দেব। যতক্ষণ না সমাধান পাওয়া যায় এভাবে চালিয়ে যাব।</p><h4>ডিএফএস</h4><p>DFS এ toCheck এর জন্য একটি <a href="https://www.geeksforgeeks.org/stack-data-structure/">স্ট্যাক</a> ব্যবহার করতে হবে।</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcarbon.now.sh%2Fembed%3Fbg%3Drgba%28255%252C255%252C255%252C1%29%26t%3Dmaterial%26wt%3Dnone%26l%3Djavascript%26ds%3Dtrue%26dsyoff%3D16px%26dsblur%3D9px%26wc%3Dtrue%26wa%3Dtrue%26pv%3D25px%26ph%3D22px%26ln%3Dfalse%26fm%3DFira%2520Code%26fs%3D14px%26lh%3D133%2525%26si%3Dfalse%26es%3D4x%26wm%3Dfalse%26code%3Dclass%252520Node%252520%25257B%25250A%252520%252520constructor%28config%25252C%252520prev%252520%25253D%252520null%25252C%252520move%252520%25253D%252520null%29%252520%25257B%25250A%252520%252520%252520%252520this.config%252520%25253D%252520config%25253B%25250A%252520%252520%252520%252520this.move%252520%25253D%252520move%25253B%25250A%252520%252520%252520%252520this.prev%252520%25253D%252520prev%25253B%25250A%252520%252520%25257D%25250A%25250A%252520%252520solved%28%29%252520%25257B...%25250A%252520%252520%25257D%25250A%252520%252520neighbors%28%29%252520%25257B...%25250A%252520%252520%25257D%25250A%252520%252520getMoves%28%29%252520%25257B...%25250A%252520%252520%25257D%25250A%25257D%25250A%25250Afunction%252520dfs%28node%29%252520%25257B%25250A%252520%252520const%252520toCheck%252520%25253D%252520%25255Bnode%25255D%25253B%25250A%252520%252520const%252520checked%252520%25253D%252520new%252520Set%28%29%25253B%25250A%25250A%252520%252520while%252520%28toCheck.length%252520%25253E%2525200%29%252520%25257B%25250A%252520%252520%252520%252520const%252520currentNode%252520%25253D%252520toCheck.pop%28%29%25253B%25250A%25250A%252520%252520%252520%252520if%252520%28currentNode.solved%28%29%29%252520%25257B%25250A%252520%252520%252520%252520%252520%252520return%252520currentNode.getMoves%28%29%25253B%25250A%252520%252520%252520%252520%25257D%25250A%25250A%252520%252520%252520%252520checked.add%28currentNode.str%29%25253B%25250A%25250A%252520%252520%252520%252520for%252520%28const%252520node%252520of%252520currentNode.neighbors%28%29%29%252520%25257B%25250A%252520%252520%252520%252520%252520%252520if%252520%28%21checked.has%28node.str%29%29%252520%25257B%25250A%252520%252520%252520%252520%252520%252520%252520%252520toCheck.push%28node%29%25253B%25250A%252520%252520%252520%252520%252520%252520%25257D%25250A%252520%252520%252520%252520%25257D%25250A%252520%252520%25257D%25250A%25257D&amp;url=https%3A%2F%2Fcarbon.now.sh%2F%3Fbg%3Drgba%28255%25252C255%25252C255%25252C1%29%26t%3Dmaterial%26wt%3Dnone%26l%3Djavascript%26ds%3Dtrue%26dsyoff%3D16px%26dsblur%3D9px%26wc%3Dtrue%26wa%3Dtrue%26pv%3D25px%26ph%3D22px%26ln%3Dfalse%26fm%3DFira%252520Code%26fs%3D14px%26lh%3D133%252525%26si%3Dfalse%26es%3D4x%26wm%3Dfalse%26code%3Dclass%25252520Node%25252520%2525257B%2525250A%25252520%25252520constructor%28config%2525252C%25252520prev%25252520%2525253D%25252520null%2525252C%25252520move%25252520%2525253D%25252520null%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520this.config%25252520%2525253D%25252520config%2525253B%2525250A%25252520%25252520%25252520%25252520this.move%25252520%2525253D%25252520move%2525253B%2525250A%25252520%25252520%25252520%25252520this.prev%25252520%2525253D%25252520prev%2525253B%2525250A%25252520%25252520%2525257D%2525250A%2525250A%25252520%25252520solved%28%29%25252520%2525257B...%2525250A%25252520%25252520%2525257D%2525250A%25252520%25252520neighbors%28%29%25252520%2525257B...%2525250A%25252520%25252520%2525257D%2525250A%25252520%25252520getMoves%28%29%25252520%2525257B...%2525250A%25252520%25252520%2525257D%2525250A%2525257D%2525250A%2525250Afunction%25252520dfs%28node%29%25252520%2525257B%2525250A%25252520%25252520const%25252520toCheck%25252520%2525253D%25252520%2525255Bnode%2525255D%2525253B%2525250A%25252520%25252520const%25252520checked%25252520%2525253D%25252520new%25252520Set%28%29%2525253B%2525250A%2525250A%25252520%25252520while%25252520%28toCheck.length%25252520%2525253E%252525200%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520const%25252520currentNode%25252520%2525253D%25252520toCheck.pop%28%29%2525253B%2525250A%2525250A%25252520%25252520%25252520%25252520if%25252520%28currentNode.solved%28%29%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520return%25252520currentNode.getMoves%28%29%2525253B%2525250A%25252520%25252520%25252520%25252520%2525257D%2525250A%2525250A%25252520%25252520%25252520%25252520checked.add%28currentNode.str%29%2525253B%2525250A%2525250A%25252520%25252520%25252520%25252520for%25252520%28const%25252520node%25252520of%25252520currentNode.neighbors%28%29%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520if%25252520%28%21checked.has%28node.str%29%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520%25252520%25252520toCheck.push%28node%29%2525253B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520%2525257D%2525250A%25252520%25252520%25252520%25252520%2525257D%2525250A%25252520%25252520%2525257D%2525250A%2525257D&amp;image=https%3A%2F%2Fcarbon.now.sh%2Fstatic%2Fbanner.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=now" width="1024" height="473" frameborder="0" scrolling="no"><a href="https://medium.com/media/7c5dcb7873338a9ac603a5de89599004/href">https://medium.com/media/7c5dcb7873338a9ac603a5de89599004/href</a></iframe><p>ট্রাই করুন: (অ্যারো কি ব্যাবহার করে এলোমেলো করতে পারেন)</p><p><a href="https://mup5k.codesandbox.io/">React App</a></p><p>কাজ চলে। শুধু ছ‌োট্ট একটি সমস্যা হল → → ↓ দিয়ে এলোমেলো করা হলে প্রায় এক লক্ষেরও বেশি স্টেপওয়ালা সমাধান বের হয়! যেখানে মাত্র তিন স্টেপেই সমাধান হওয়ার কথা।</p><p>এমনটা কেন হচ্ছে? কারণ DFS বা ‘ডেপথ্ ফার্স্ট সার্চ’ এর মানেই হল গ্রাফের সবচেয়ে গভীরে আগে খুঁজবে। ব্যাপারটা অনেকটা এমন হচ্ছে:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/761/1*NHEWnWyc9YTk9O--r6jNBA.png" /></figure><h4>বিএফএস</h4><p>তারপর আসা যাক BFS এ। আমরা জানি BFS একটি শর্টেস্ট পাথ অ্যালগরিদম। DFS এর সাথে এর পার্থক্য হল শুধু স্ট্যাকের বদলে <a href="https://www.geeksforgeeks.org/queue-data-structure/">কিউ</a> ব্যবহার করতে হয়। এতে করে গ্রাফের গভীরে যাওয়ার আগে কাছের নোডগুলো আগে ভিজিট হয়। (জাভাস্ক্রিপ্টে স্ট্যাক, কিউ দুটোর কাজই অ্যারে দিয়ে চালানো যায়। .pop() করলে শেষের উপাদান পওয়া যায় আর .shift() করলে সামনের)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcarbon.now.sh%2Fembed%3Fbg%3Drgba%28255%252C255%252C255%252C1%29%26t%3Dmaterial%26wt%3Dnone%26l%3Djavascript%26ds%3Dtrue%26dsyoff%3D16px%26dsblur%3D15px%26wc%3Dtrue%26wa%3Dtrue%26pv%3D44px%26ph%3D25px%26ln%3Dfalse%26fm%3DFira%2520Code%26fs%3D14px%26lh%3D133%2525%26si%3Dfalse%26es%3D4x%26wm%3Dfalse%26code%3Dfunction%252520bfs%28node%29%252520%25257B%25250A%252520%252520const%252520toCheck%252520%25253D%252520%25255Bnode%25255D%25253B%25250A%252520%252520const%252520checked%252520%25253D%252520new%252520Set%28%29%25253B%25250A%25250A%252520%252520while%252520%28toCheck.length%252520%25253E%2525200%29%252520%25257B%25250A%252520%252520%252520%252520const%252520currentNode%252520%25253D%252520toCheck.shift%28%29%25253B%25250A%25250A%252520%252520%252520%252520if%252520%28currentNode.solved%28%29%29%252520%25257B%25250A%252520%252520%252520%252520%252520%252520return%252520currentNode.getMoves%28%29%25253B%25250A%252520%252520%252520%252520%25257D%25250A%25250A%252520%252520%252520%252520checked.add%28currentNode.str%29%25253B%25250A%25250A%252520%252520%252520%252520for%252520%28const%252520node%252520of%252520currentNode.neighbors%28%29%29%252520%25257B%25250A%252520%252520%252520%252520%252520%252520if%252520%28%21checked.has%28node.str%29%29%252520%25257B%25250A%252520%252520%252520%252520%252520%252520%252520%252520toCheck.push%28node%29%25253B%25250A%252520%252520%252520%252520%252520%252520%25257D%25250A%252520%252520%252520%252520%25257D%25250A%252520%252520%25257D%25250A%25257D&amp;url=https%3A%2F%2Fcarbon.now.sh%2F%3Fbg%3Drgba%28255%25252C255%25252C255%25252C1%29%26t%3Dmaterial%26wt%3Dnone%26l%3Djavascript%26ds%3Dtrue%26dsyoff%3D16px%26dsblur%3D15px%26wc%3Dtrue%26wa%3Dtrue%26pv%3D44px%26ph%3D25px%26ln%3Dfalse%26fm%3DFira%252520Code%26fs%3D14px%26lh%3D133%252525%26si%3Dfalse%26es%3D4x%26wm%3Dfalse%26code%3Dfunction%25252520bfs%28node%29%25252520%2525257B%2525250A%25252520%25252520const%25252520toCheck%25252520%2525253D%25252520%2525255Bnode%2525255D%2525253B%2525250A%25252520%25252520const%25252520checked%25252520%2525253D%25252520new%25252520Set%28%29%2525253B%2525250A%2525250A%25252520%25252520while%25252520%28toCheck.length%25252520%2525253E%252525200%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520const%25252520currentNode%25252520%2525253D%25252520toCheck.shift%28%29%2525253B%2525250A%2525250A%25252520%25252520%25252520%25252520if%25252520%28currentNode.solved%28%29%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520return%25252520currentNode.getMoves%28%29%2525253B%2525250A%25252520%25252520%25252520%25252520%2525257D%2525250A%2525250A%25252520%25252520%25252520%25252520checked.add%28currentNode.str%29%2525253B%2525250A%2525250A%25252520%25252520%25252520%25252520for%25252520%28const%25252520node%25252520of%25252520currentNode.neighbors%28%29%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520if%25252520%28%21checked.has%28node.str%29%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520%25252520%25252520toCheck.push%28node%29%2525253B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520%2525257D%2525250A%25252520%25252520%25252520%25252520%2525257D%2525250A%25252520%25252520%2525257D%2525250A%2525257D&amp;image=https%3A%2F%2Fcarbon.now.sh%2Fstatic%2Fbanner.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=now" width="1024" height="473" frameborder="0" scrolling="no"><a href="https://medium.com/media/2a487ed8608817780b954acb24491288/href">https://medium.com/media/2a487ed8608817780b954acb24491288/href</a></iframe><p><a href="https://s5okj.codesandbox.io/">React App</a></p><p>কয়েকবার Jumble করে dfs() ও bfs() করে দেখুন। বিএফএস যে শুধু শর্টেস্ট পাথ দেয় তা না, সময়ও বেশ কম লাগে। চমৎকার। তাই না? মনে হতে পারে BFS DFS কে <em>অক্করে হুতাই লাইসে</em>। তাহলে এই কনফিগারেশনটি ট্রাই করুন:</p><p><a href="https://f3gu2.codesandbox.io/">React App</a></p><p>কি দেখলেন? DFS থেকে BFS বেশ কয়েকগুন বেশি সময় নেয়। কেন? কারণ শুরুর নোডটি একটু বেশি এলোমেলো হলে বিএফএস এর অবস্থা টাইট হয়ে যায়। কাছের নোডগুলো আগে চেক করতে গিয়ে ফইনাল নোড যত গভীরে আছে সেই গভীরতা পর্যন্ত সকল নোড চেক করতে হয়। এজন্য কনফিগারেশনটি একটু বেশি এলোমেলো হলে আর্থাৎ সলিউশন নোড খুব দূরে হলে বিশাল সংখ্যক নোড চেক করতে হয়। এতে সময় যেমন বেশি লাগে আবার চেক করা নোডগুলো হিসেব রাখতে মেমরিও বেশি লাগে।</p><p>(কিছু কিছু ডিভাইসে এই কনফিগারেশনটির জন্যও BFS DFS থেকে ভাল পারফর্ম করতে পারে। সেক্ষেত্রে আরো চার-পাঁচবার jumble ক্লিক করে এলোমেলো করে ট্রাই করুন।)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/761/1*zy3cs4lxPh7DiZyXwF-jDw.png" /></figure><p>চিত্রে দেখতে পাচ্ছে সলিউশন নোডের দূরত্ব শুরুর নোড থেকে ৩। BFS এর ক্ষেত্রে তিন দূরত্বের সকল নোড চেক করতে হবে। বুঝতেই পারছেন দূরত্ব বাড়ার সাথে সাথে চেক করা নোডের সংখ্যা খুব দ্রুত বাড়বে।</p><h4>A* সার্চ</h4><p>এখানে দুটো অ্যাপ্রোচের সমস্যা মুটামুটি একই। কোন নোডগুলো আগে চেক করতে হবে ঠিক করতে না পারা। কাছেরগুলো আগে চেক করলে অনেকগুলো চেক করতে হয়। আর গভীরেরগুলো আগে চেক করলে কাছের সলিউশন ফসকে যায়। কোন নোডগুলো আগে চেক করতে হবে সেটা যদি শুধু একটু বুদ্ধি করে ঠিক করা যেত!</p><p>আমরা যা করব তা হল প্রতিটি নোডের একটি কস্ট হিসেব করব। তারপর তারপর `toCheck` এর জন্য স্ট্যাক কিংবা কিউ ব্যবহার না করে <a href="https://en.wikipedia.org/wiki/Priority_queue">প্রায়োরিটি কিউ</a> ব্যবহার করব। তহলে সবচেয়ে কম কস্টওয়ালা নোডগুলো আগে চেক হবে।</p><p>একটি নোডের কস্ট কিভাবে হিসেব করা যায়? নোডটি থেকে সলিউশন নোডের দূরত্ব আর শুরুর নোডের দূরত্বের যোগফল একটি কস্ট হতে পারে। অবশ্যই, নোডটি সলিউশন নোড থেকে কতটা দূরে আছে সেটা কারেক্টলি বের করার কোন সহজ উপায় নেই। আমরা মুটামুটি আনুমানিক একটি দূরত্ব নিতে পারি। যেমন এই ফাংশনটি ব্যাবহার করা যায়:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcarbon.now.sh%2Fembed%3Fbg%3Drgba%28255%252C255%252C255%252C1%29%26t%3Dmaterial%26wt%3Dnone%26l%3Djavascript%26ds%3Dtrue%26dsyoff%3D16px%26dsblur%3D15px%26wc%3Dtrue%26wa%3Dtrue%26pv%3D44px%26ph%3D25px%26ln%3Dfalse%26fm%3DFira%2520Code%26fs%3D14px%26lh%3D133%2525%26si%3Dfalse%26es%3D4x%26wm%3Dfalse%26code%3Dfunction%252520dist%28config%29%252520%25257B%25250A%252520%252520return%252520config.reduce%28%28prev%25252C%252520cur%25252C%252520i%29%252520%25253D%25253E%252520%25257B%25250A%252520%252520%252520%252520cur%252520%25253D%252520%28cur%252520%25257C%25257C%2525209%29%252520-%2525201%25253B%25250A%252520%252520%252520%252520return%252520%28%25250A%252520%252520%252520%252520%252520%252520prev%252520%25252B%252520Math.abs%28%28cur%2525253%29%252520-%252520%28i%2525253%29%29%252520%25252B%252520Math.abs%28%7E%7E%28cur%25252F3%29%252520%25252B%252520%7E%7E%28i%25252F3%29%29%25250A%252520%252520%252520%252520%29%25253B%25250A%252520%252520%25257D%25252C%2525200%29%25253B%25250A%25257D&amp;url=https%3A%2F%2Fcarbon.now.sh%2F%3Fbg%3Drgba%28255%25252C255%25252C255%25252C1%29%26t%3Dmaterial%26wt%3Dnone%26l%3Djavascript%26ds%3Dtrue%26dsyoff%3D16px%26dsblur%3D15px%26wc%3Dtrue%26wa%3Dtrue%26pv%3D44px%26ph%3D25px%26ln%3Dfalse%26fm%3DFira%252520Code%26fs%3D14px%26lh%3D133%252525%26si%3Dfalse%26es%3D4x%26wm%3Dfalse%26code%3Dfunction%25252520dist%28config%29%25252520%2525257B%2525250A%25252520%25252520return%25252520config.reduce%28%28prev%2525252C%25252520cur%2525252C%25252520i%29%25252520%2525253D%2525253E%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520cur%25252520%2525253D%25252520%28cur%25252520%2525257C%2525257C%252525209%29%25252520-%252525201%2525253B%2525250A%25252520%25252520%25252520%25252520return%25252520%28%2525250A%25252520%25252520%25252520%25252520%25252520%25252520prev%25252520%2525252B%25252520Math.abs%28%28cur%252525253%29%25252520-%25252520%28i%252525253%29%29%25252520%2525252B%25252520Math.abs%28%7E%7E%28cur%2525252F3%29%25252520%2525252B%25252520%7E%7E%28i%2525252F3%29%29%2525250A%25252520%25252520%25252520%25252520%29%2525253B%2525250A%25252520%25252520%2525257D%2525252C%252525200%29%2525253B%2525250A%2525257D&amp;image=https%3A%2F%2Fcarbon.now.sh%2Fstatic%2Fbanner.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=now" width="1024" height="473" frameborder="0" scrolling="no"><a href="https://medium.com/media/0989bb699668c233d837462e02708d37/href">https://medium.com/media/0989bb699668c233d837462e02708d37/href</a></iframe><p>কোড বুঝতে আসুবিধা হলে চিন্তার কিছু নেই। ফাংশনটি প্রতিটি স্কয়ার তার প্রত্যাশিত অবস্থান থেকে কতটা দূরে আছে সেটার যোগফল দেয়। আর এখানে স্কয়ারের দূরত্বের জন্য সাধারণ <a href="https://en.wikipedia.org/wiki/Euclidean_distance">ইউক্লিডিয়ান দূরত্ব</a> ব্যবহার না করে আরো সিম্পল ফর্মুলা ব্যবহার করা হয়েছে। জাস্ট x ও y অক্ষে পার্থক্যের যোগফল। একে <a href="https://www.quora.com/What-is-Manhattan-Distance">ম্যানহ্যাটন ডিসট্যান্স</a> বলে।</p><p>এমন আনুমানিক কস্টকে <a href="https://en.wikipedia.org/wiki/Heuristic_(computer_science)">হিউরিস্টিক</a> বলা হয়ে থাকে। আর A* সার্চ হল একটি হিউরিস্টিক সার্চ অ্যালগরিদম। সব ধরণের গ্রাফে হয়ত এটি ব্যবহার করা যাবে না। কারণ অনেক কোন রকম হিউরিস্টিক হিসেব করার কোন সুযোগ নেই।</p><p>নোড ক্লাসে কিছু পরিবর্তনসহ এই হল A* কোড: (প্রায়োরিটি কিউ <a href="https://github.com/mourner/tinyqueue/blob/master/index.js">এখান</a> থেকে নেয়া হয়েছে)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcarbon.now.sh%2Fembed%3Fbg%3Drgba%28255%252C255%252C255%252C1%29%26t%3Dmaterial%26wt%3Dnone%26l%3Djavascript%26ds%3Dtrue%26dsyoff%3D16px%26dsblur%3D15px%26wc%3Dtrue%26wa%3Dtrue%26pv%3D44px%26ph%3D25px%26ln%3Dfalse%26fm%3DFira%2520Code%26fs%3D14px%26lh%3D133%2525%26si%3Dfalse%26es%3D4x%26wm%3Dfalse%26code%3Dclass%252520Node%252520%25257B%25250A%252520%252520constructor%28config%25252C%252520prev%252520%25253D%252520null%25252C%252520move%252520%25253D%252520null%25252C%252520depth%252520%25253D%2525200%29%252520%25257B%25250A%252520%252520%252520%252520this.config%252520%25253D%252520config%25253B%25250A%252520%252520%252520%252520this.str%252520%25253D%252520config.join%28%29%25253B%25250A%252520%252520%252520%252520this.move%252520%25253D%252520move%25253B%25250A%252520%252520%252520%252520this.prev%252520%25253D%252520prev%25253B%25250A%25250A%252520%252520%252520%252520this.depth%252520%25253D%252520depth%25253B%25250A%252520%252520%252520%252520this.cost%252520%25253D%252520depth%252520%25252B%252520dist%28config%29%25253B%25250A%252520%252520%25257D%25250A%252520%252520...%25250A%25257D%25250A%25250A%25250Afunction%252520ast%28node%29%252520%25257B%25250A%252520%252520const%252520toCheck%252520%25253D%252520new%252520PriorityQueue%28%25255Bnode%25255D%25252C%252520%28a%25252C%252520b%29%252520%25253D%25253E%252520a.cost%252520-%252520b.cost%29%25253B%25250A%252520%252520const%252520checked%252520%25253D%252520new%252520Set%28%29%25253B%25250A%25250A%252520%252520while%252520%28toCheck.length%252520%25253E%2525200%29%252520%25257B%25250A%252520%252520%252520%252520const%252520currentNode%252520%25253D%252520toCheck.pop%28%29%25253B%25250A%25250A%252520%252520%252520%252520if%252520%28currentNode.solved%28%29%29%252520%25257B%25250A%252520%252520%252520%252520%252520%252520return%252520currentNode.getMoves%28%29%25253B%25250A%252520%252520%252520%252520%25257D%25250A%25250A%252520%252520%252520%252520checked.add%28currentNode.str%29%25253B%25250A%25250A%252520%252520%252520%252520for%252520%28const%252520node%252520of%252520currentNode.neighbors%28%29%29%252520%25257B%25250A%252520%252520%252520%252520%252520%252520if%252520%28%21checked.has%28node.str%29%29%252520%25257B%25250A%252520%252520%252520%252520%252520%252520%252520%252520toCheck.push%28node%29%25253B%25250A%252520%252520%252520%252520%252520%252520%25257D%25250A%252520%252520%252520%252520%25257D%25250A%252520%252520%25257D%25250A%25257D&amp;url=https%3A%2F%2Fcarbon.now.sh%2F%3Fbg%3Drgba%28255%25252C255%25252C255%25252C1%29%26t%3Dmaterial%26wt%3Dnone%26l%3Djavascript%26ds%3Dtrue%26dsyoff%3D16px%26dsblur%3D15px%26wc%3Dtrue%26wa%3Dtrue%26pv%3D44px%26ph%3D25px%26ln%3Dfalse%26fm%3DFira%252520Code%26fs%3D14px%26lh%3D133%252525%26si%3Dfalse%26es%3D4x%26wm%3Dfalse%26code%3Dclass%25252520Node%25252520%2525257B%2525250A%25252520%25252520constructor%28config%2525252C%25252520prev%25252520%2525253D%25252520null%2525252C%25252520move%25252520%2525253D%25252520null%2525252C%25252520depth%25252520%2525253D%252525200%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520this.config%25252520%2525253D%25252520config%2525253B%2525250A%25252520%25252520%25252520%25252520this.str%25252520%2525253D%25252520config.join%28%29%2525253B%2525250A%25252520%25252520%25252520%25252520this.move%25252520%2525253D%25252520move%2525253B%2525250A%25252520%25252520%25252520%25252520this.prev%25252520%2525253D%25252520prev%2525253B%2525250A%2525250A%25252520%25252520%25252520%25252520this.depth%25252520%2525253D%25252520depth%2525253B%2525250A%25252520%25252520%25252520%25252520this.cost%25252520%2525253D%25252520depth%25252520%2525252B%25252520dist%28config%29%2525253B%2525250A%25252520%25252520%2525257D%2525250A%25252520%25252520...%2525250A%2525257D%2525250A%2525250A%2525250Afunction%25252520ast%28node%29%25252520%2525257B%2525250A%25252520%25252520const%25252520toCheck%25252520%2525253D%25252520new%25252520PriorityQueue%28%2525255Bnode%2525255D%2525252C%25252520%28a%2525252C%25252520b%29%25252520%2525253D%2525253E%25252520a.cost%25252520-%25252520b.cost%29%2525253B%2525250A%25252520%25252520const%25252520checked%25252520%2525253D%25252520new%25252520Set%28%29%2525253B%2525250A%2525250A%25252520%25252520while%25252520%28toCheck.length%25252520%2525253E%252525200%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520const%25252520currentNode%25252520%2525253D%25252520toCheck.pop%28%29%2525253B%2525250A%2525250A%25252520%25252520%25252520%25252520if%25252520%28currentNode.solved%28%29%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520return%25252520currentNode.getMoves%28%29%2525253B%2525250A%25252520%25252520%25252520%25252520%2525257D%2525250A%2525250A%25252520%25252520%25252520%25252520checked.add%28currentNode.str%29%2525253B%2525250A%2525250A%25252520%25252520%25252520%25252520for%25252520%28const%25252520node%25252520of%25252520currentNode.neighbors%28%29%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520if%25252520%28%21checked.has%28node.str%29%29%25252520%2525257B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520%25252520%25252520toCheck.push%28node%29%2525253B%2525250A%25252520%25252520%25252520%25252520%25252520%25252520%2525257D%2525250A%25252520%25252520%25252520%25252520%2525257D%2525250A%25252520%25252520%2525257D%2525250A%2525257D&amp;image=https%3A%2F%2Fcarbon.now.sh%2Fstatic%2Fbanner.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=now" width="1024" height="473" frameborder="0" scrolling="no"><a href="https://medium.com/media/8374aae633e4283fcb902b63d8439d41/href">https://medium.com/media/8374aae633e4283fcb902b63d8439d41/href</a></iframe><p><a href="https://6rp8o.codesandbox.io/">React App</a></p><p>সম্পূর্ণ কোড <a href="https://github.com/sjsakib/blog/tree/master/src/posts/may-2019/SlidingPuzzle">এখানে</a> পাবেন। শুধু সলিউশনের কোডের জন্য <a href="https://github.com/sjsakib/blog/blob/master/src/posts/may-2019/SlidingPuzzle/solve.js">এই ফাইলটি</a> দেখুন। যদি ভাল লেগে থাকে তাহলে উপরে ডানে স্টার বাটনটি একটু চেপে দিলে ভাল লাগবে।</p><p>লেখাটি প্রথমে আমার ব্লগে প্রকাশিত হয়েছি।</p><p>লিংক: <a href="https://sakib.dev/blog/a-star-search/">https://sakib.dev/blog/a-star-search/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7b74704405de" width="1" height="1" alt=""><hr><p><a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/a-%E0%A6%B8%E0%A6%BE%E0%A6%B0%E0%A7%8D%E0%A6%9A-7b74704405de">A* সার্চ</a> was originally published in <a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE">প্রোগ্রামিং পাতা</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[রিঅ্যাক্ট হুক]]></title>
            <link>https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/%E0%A6%B0%E0%A6%BF%E0%A6%85%E0%A7%8D%E0%A6%AF%E0%A6%BE%E0%A6%95%E0%A7%8D%E0%A6%9F-%E0%A6%B9%E0%A7%81%E0%A6%95-12fc6df140ed?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/12fc6df140ed</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[react-hook]]></category>
            <category><![CDATA[bangla]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Fri, 15 Mar 2019 05:22:51 GMT</pubDate>
            <atom:updated>2019-03-15T06:00:08.092Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*llOYC19xmp1keuw6" /><figcaption>Photo by <a href="https://unsplash.com/@ckirby?utm_source=medium&amp;utm_medium=referral">Cameron Kirby</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>হুক এতদিনে পুরনো হয়ে গেলেও ইয়ার ফাইনালের চক্করে প্রোগ্রামিং থেকে দূরে থাকায় ট্রাই করে দেখা হয়নি। তাই আজকে একটু ঘেটে দেখার সময় ভাবলাম লেখার চেষ্টা করা যেতে পারে, যেহেতু অনেকদিন কিছু লেখাও হয়নি।</p><p>হুক কি এবং কেন সেটায় বিস্তারিত যাব না। সংক্ষেপে বলি। হুক রিঅ্যাক্টের নতুন এপিআই। হুক ব্যবহার করে ফাংশনাল কম্পোনেন্টেই স্টেট ম্যানেজ করা যায়, লাইফসাইকেল মেথডের কাজও করা যায়। অর্থাৎ হুক ব্যবহার করলে ক্লাস বেসড্ কম্পোনেন্ট ছাড়াই সব ধরণের ফাংশনালিটি ইম্প্লিমেন্ট করা যায়। এতে যা সুবিধা হয় তা হল অনেকগুলো কম্পোনেন্টের মধ্যে স্টেট রিলেটেট লজিক শেয়ার করা যায়। মানে একাধিক কম্পোনেন্টের একই কাছাকাছি স্টেট লজিক থাকলে সেটা প্রত্যেক কম্পোনেন্টে বার বার ইম্প্লিমেন্ট না করে কাস্টম হুকের মাধ্যামে একবার ইম্প্লিমেন্ট করে রিইউজ করা যায়। তাছাড়া হুকের মাধ্যমে একই কম্পোনেন্টের বিভিন্ন ফাংশনালিটি আলাদা আলাদা করে লেখা যায় বলে বড় ও জটিল কম্পোনেন্ট সিম্পল হয়। বিস্তারিত <a href="https://reactjs.org/docs/hooks-intro.html">এখানে</a> দেখতে পারেন।</p><p>তাহলে আর কথা না বাড়িয়ে সরাসরি অ্যাকশনে হুক দেখব। তাহলে হুক দিয়ে একটি ছোটখাট অ্যাপ বানিয়ে ফেলা যাক। কি অ্যাপ বানানো যায় ভাবতে গিয়ে দেখলাম একটি অ্যাপ আছে যেটি মনে হয় সব ফ্রন্টএ্যান্ড ডেভেলাপার ই কোন না কোন সময়ে বানায় কিন্তু আমি এই পর্যন্ত বানাইনি। ওয়েদার অ্যাপ :D</p><h4>স্টেট হুক</h4><p>প্রথমেই লোকেশন ইনপুট নেয়া যাক।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7ThI_5J5SQEJiao31X1kkQ.png" /></figure><p>এখানে দেখতে পাচ্ছেন react প্যাকেজ থেকে React এর পাশাপাশি useState ফাংশন ইম্পোর্ট করে নিচ্ছি যা রিঅ্যাক্টের 16.8 ভার্সন থেকে পাওয়া যাচ্ছে। ফাংশনাল কম্পোনেন্টের ভেতরে useState কল করলে একটা অ্যারে রিটার্ন করে যার প্রথম উপাদান একটি স্টেট ভ্যালু আর দ্বিতীয় উপাদন হল ঐ স্টেট পরিবর্তন করার জন্য একটি ফাংশন। আমার এখানে <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Array_destructuring">অ্যারে ডিস্ট্রাকশন</a> সিনট্যাক্সের মাধ্যমে এই দুটি উপাদানকে দুটি ভ্যারিয়েবলে নিয়ে নিচ্ছি। এখানে useState এর একমাত্র আর্গুমেন্ট হল স্টেটের প্রাথমিক ভ্যালু। এখন setLocation ফাংশনটি আমরা এই ফাংশনাল কম্পোনেন্টের যেকোন জায়গায় কল করে location স্টেট চেন্জ করতে পারব। স্টেট চেন্জ হলে কম্পোনেন্ট রি-রেন্ডার হবে। অর্থাৎ আমাদের পুরো কম্পোনেন্ট ফাংশনটি আবার কল হবে। এর ভেতরে useState ফাংশনটিও আবার একই আর্গুমেন্টে কল হবে। কিন্তু এইবার রিটার্ন করা অ্যারের প্রথম উপাদানে আর্গুমেন্টে দেয়া ভ্যালুর বদলে পরিবর্তিত নতুন স্টেট ভ্যালু থাকবে। দ্বিতীয় উপাদানে আগের মতই স্টেট পরিবর্তন করার জন্য একটি ফাংশন থাকবে। আমরা চাইলে কোন একটি কম্পোনেন্টে একাধিক স্টেটের জন্য একাধিক বার useState কল করতে পারি।</p><p>আসলে প্রথমবার কোন কম্পোনেন্ট থেকে useState কল করলে রিঅ্যাক্ট ঐ কম্পোনেন্টের সাথে এসোসিয়েট করে একটি মেমরি সেল তৈরী করে ঐখানে আমাদের প্রাথমিক ভ্যালু রেখে দেয় ও একটি ফাংশন দেয় যা দিয়ে ঐ মেমরি সেল মডিফাই করা যাবে। ঐ কম্পোনেন্টে আবার useState ব্যবহার করলে নতুন একটি মেমরি সেল তৈরী হয়। কম্পোনেন্ট রি-রেন্ডার হলে মেমরি সেলের কার্সরটি প্রথম সেলে চলে যায় এবং নতুন সেল তৈরী করার বদলে পুরনো সেলগুলো থেকে সিরিয়ালে স্টেটগুলো রিটার্ণ করতে থাকে। তাই খেয়াল রাখতে হবে যেন প্রতি রেন্ডারে হুকগুলোর সিরিয়াল একই থাকে।</p><p>তাহলে এখন এপিআই গুতা দিয়ে ওয়েদার ডেটা নিয়ে আসা যাক। ডেটা আর মেসেজ রাখার জন্য আরো দুটি হুক ব্যবহার করব।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T3yUP_8wmBgzErhXPcUVwQ.png" /><figcaption>মুটামুটি চলে?</figcaption></figure><h4>ইফেক্ট হুক</h4><p>লোকেশন অটো ডিটেক্ট করতে পারলে ভাল হত না? ক্লাস বেসড কম্পোনেন্টে আমরা componentDidMound এ লোকেশন এপিআই ব্যবহার করে লোকেশন ডিটেক্ট করতে পারতাম। এখনে আমরা useEffect হুক ব্যবহার করব।</p><p>useEffect হুকটিও একটি ফাংশন। এতে একটি কলব্যাক পাস করতে হয়। প্রত্যেকবার কম্পোনেন্ট রেন্ডার হওয়ার পর এই কলব্যাকটি কল হয়। কলব্যাকের পাশাপাশি একটি অ্যারে পাস করা যায়। এতে কলব্যাকটি প্রথমবার রেন্ডারের পর স্বাভাবিকভাবে কল হবে। কিন্তু পরবর্তী রেন্ডারের পর শুধু যদি অ্যারের উপাদানগুলো চেন্জ হয় তবেই কল হবে।</p><p>এখন যদি শুধু একটি খালি অ্যারে পাস করি, তাহলে কলব্যাকটি শুধু প্রথমবার রেন্ডার হবে। অর্থাৎ ঠিক componentDidMount এর মত কাজ করবে। এখানে এটাই আমাদের দরকার।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FvqL3PJ5O1stVjWxlhJ_iw.png" /><figcaption>ডেটা ফেচ করার জন্য আলাদা একটা ফাংশন ডিফাইন করে নেয়া হয়েছে</figcaption></figure><p>এখানে দরাকারি না হলে বলে রাখা ভাল যে, আমরা চাইলে ইফেক্টের কলব্যাক থেকে আবার একটি কলব্যাক রিটার্ণ করতে পারি। ইফেক্ট কলব্যাকটি আবার রান হওয়ার আগে এটি রান হবে। আর যদি useEffect এ খালি অ্যারে পাস করি মানে যদি ইফেক্ট কলব্যাকটি প্রথম রেন্ডারের পর রান হওয়ার পরে আর রান না হয় তাহলে কম্পোনেন্ট আনমাউন্ট হওয়ার সময় রান হবে। অর্থাৎ ঠিক componentDidUnmout এর মত কাজ করবে।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_5V25xUritolVWSc-wVp0A.png" /><figcaption>ইফেক্ট হুক</figcaption></figure><h4>কাস্টম হুক</h4><p>হুক ব্যবহার করার সবচেয়ে বড় সুবিধা হল আমরা কোন কম্পোন্টের একটি নির্দিষ্ট ফাংশনালিটি একটি কাস্টম হুকের ভেতরে ঢুকিয়ে ফেলতে পারি এবং পরে চাইলে অন্য কম্পোনেন্টেও এই ফাংশনালিটি খুব সহজেই এড করতে পারি।</p><p>কাস্টম হুক ডিফাইন করা খুবই সোজা। আসলে কাস্টম হুক সাধারণ ফাংশন ছাড়া আর কিছুই না। এই ফাংশনগুলোতে আমরা অন্যান্য হুক ব্যবহার করি। উদাহরণের মাধ্যমে দেখে নিই।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KYAEwAsBLJVWQ_xRfaOZjQ.png" /><figcaption>এখানে ইনপুট নেয়ার ফাংশনালিটি ছাড়া বাকি সব ফাংশনালিটি হুকে নিয়ে নেয়া হয়েছে।</figcaption></figure><p>হুকের নামের আগে use ব্যবহার করাটা একটা কনভেনশন। এখনে যদিও কাস্টম হুক খুব একটা বাড়তি সুবিধা দিচ্ছে না। কিন্তু বড় এবং জটিল অ্যাপ্লিকেশন ডেভেলাপ করার সময় কাস্টম হুক খুব কাজের হতে পারে।</p><h4>শেষ কথা</h4><p>আসলে হুক বেসড্ কম্পোনেন্টগুলো একটু অন্য রকম হবে। হুক নিয়ে কাজ করতে হলে ক্লাস বেসড্ কম্পোনেন্ট থেকে একটু ভিন্নভাবে চিন্তা করতে হবে।</p><p>আমি নিজে ব্যাক্তিগতভাবে পরবর্তী সব প্রজেক্ট শুধু হুক দিয়ে করার চেষ্টা করব। তবে হুক ব্যবহারের ক্ষেত্রে যে জিনিসটা আমার ভাল লাগে না সেটা হল ফাংশনের ভেতরে প্রচুর ফাংশন ডিফাইন করতে হয়।</p><p>আপনার মতামত কি? সমানের প্রজেক্টগুলোতে হুক ব্যবহার করবেন? নাকি ক্লাস বেসড্ ফাংশনই ব্যবহার করতে থাকবেন?</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=12fc6df140ed" width="1" height="1" alt=""><hr><p><a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/%E0%A6%B0%E0%A6%BF%E0%A6%85%E0%A7%8D%E0%A6%AF%E0%A6%BE%E0%A6%95%E0%A7%8D%E0%A6%9F-%E0%A6%B9%E0%A7%81%E0%A6%95-12fc6df140ed">রিঅ্যাক্ট হুক</a> was originally published in <a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE">প্রোগ্রামিং পাতা</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[পাইথন দিয়ে জিপির সিক্রেট অফার ডিকোড করে ফেললাম]]></title>
            <link>https://medium.com/@sjsakib/%E0%A6%AA%E0%A6%BE%E0%A6%87%E0%A6%A5%E0%A6%A8-%E0%A6%A6%E0%A6%BF%E0%A7%9F%E0%A7%87-%E0%A6%9C%E0%A6%BF%E0%A6%AA%E0%A6%BF%E0%A6%B0-%E0%A6%B8%E0%A6%BF%E0%A6%95%E0%A7%8D%E0%A6%B0%E0%A7%87%E0%A6%9F-%E0%A6%85%E0%A6%AB%E0%A6%BE%E0%A6%B0-%E0%A6%A1%E0%A6%BF%E0%A6%95%E0%A7%8B%E0%A6%A1-%E0%A6%95%E0%A6%B0%E0%A7%87-%E0%A6%AB%E0%A7%87%E0%A6%B2%E0%A6%B2%E0%A6%BE%E0%A6%AE-3e277c22b200?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/3e277c22b200</guid>
            <category><![CDATA[regular-expressions]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[offers]]></category>
            <category><![CDATA[grameenphone]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Mon, 10 Dec 2018 14:31:00 GMT</pubDate>
            <atom:updated>2018-12-10T14:31:00.961Z</atom:updated>
            <content:encoded><![CDATA[<p>একদিন জিপির কাছ থেকে এমন একটা মেসেজ পেলাম</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*YRuSoBdHLlOOLaD4rBnsxw.png" /></figure><p>কি এইটা? সিক্রেট মেসেজ? কোন সিক্রেট অফার নয়ত? সারা বছর অনলিমিটেড ইন্টারনেট? অন্তত মাসখানেক? নাহ অত খুশি হয়ে সম্ভবত লাভ নেই। কোন সমস্যার কারণেই হয়ত এমন মেসেজ চলে এসেছে। ইগনোর করতে যাচ্ছিলাম। তখন ভাবলাম যাই হোক, ডিকোড করার চেষ্টা করা যাক। ক্রিপ্টোগ্রাফি অল্প সল্প কিছু শিখেছিলাম। ( দারুণ <a href="https://inventwithpython.com/hacking/">এই বইটা</a> পড়ে) দেখা যাক কাজে লাগানো যায় কিনা। কিভাবে করা যায় ডিকোড?</p><p>দেখা যাচ্ছে টেক্সটটাতে হাবিজাবি কিছু সংখ্যা আর সাথে &amp;#;। ফরম্যাটটা এমন <em>&amp;#&lt;চার অঙ্কের সংখ্যা&gt;; </em>সংখ্যাগুলা ২৪০০-২৫০০ মধ্যে। এক জায়গায় দেখা যাচ্ছে MB আরেক জায়গায় .88 আবার *7728*2*2#। ৮৮ পয়সায় বিশাল পরিমাণ ডেটা পাওয়া যাওয়ার বিশাল সম্ভাবনা। এখানে কিছু ইংলিশ ক্যারেক্টার ঠিকঠাক। কিন্তু বাকিগুলা এনক্রিপ্টেট! তাহলে কি ইউনিকোড ক্যারেক্টারগুলা এনক্রিপ্টেট? ; দিয়ে নিশ্চয় ক্যারেক্টারগুলা আলাদা করা হয়েছে। ইউনিকোড ক্যারেক্টারের বদলে অর্ডিনাল আইসা পরে নাই ত? পাইথন নোটবুক খুলে শুরু করলাম</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/571/1*hIQ8NC34A5F-WHjSiXO-Ow.png" /></figure><p>তাই মনে হচ্ছে। ‘ক’ এর ইউনিকোড ভ্যালু ২৪৫৩। তাহলে আর ক্রিপ্টোগ্রাফির জ্ঞানবুদ্ধি কাজে লাগানো গেল না 😒 যাই হোক, মেসেজটা একটা ফাইলে পেস্ট করে পিসিতে নিয়ে আসলাম। তারপর</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/568/1*9XEAkXziDqDXM8-mQpruOA.png" /></figure><p>এখন <em>&amp;#‌‌[code]</em>; প্যাটার্নটাকে ইউনিকোড ক্যারেক্টার দিয়ে রিপ্লেস করে দিলেই হল। এখন ; দিয়ে <a href="https://docs.python.org/3.6/library/stdtypes.html#str.split">split</a> করে দেয়া যায়। তারপরে প্রত্যেকটার শেষের চারটা ক্যারেক্টার নিয়ে যে ইউনিকোড ক্যারেক্টার পাওয়া যায় সেগুলা নিয়ে আবার যোগ করে দিলেই হয়। কিন্তু সেক্ষেত্রে নন-ইউনিকোডগুলার জন্য ঝামেলা হয়ে যয়। আরো সুন্দর সলিউশন পেলে ভাল হয়।</p><p>হ্যাঁ। regex। regex দিয়ে রিপ্লেস করা যায়। এখানে প্যাটার্নটা হবে <em>&amp;#\d{4};</em> প্রত্যেকটা প্যাটার্নকে রিপ্লেস করতে হবে। ডক ঘেটে এই কাজের জন্য সুন্দর একটা ফাংশন পেয়ে গেলাম। re.sub() । এটা প্যাটার্ন রিপ্লেস করার জন্য একটা ফাংশন নেয়। তাহলে সেটা ডিফাইন করে ফেলা যাক</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/564/1*XQGGE_rU4_gQNyWnyX_92A.png" /></figure><p>এইবেলা re.sub() কল করে ফেললেই হল</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*HIja7YvM-Qve9W9gMwIOGQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/240/1*6hRV7o5GhPWOAoCTvfMwLg.jpeg" /></figure><p><em>লেখাটা বেশ আগের। ২০১৬ সালের দিকে লেখা। আজকে হঠাৎ সামনে আসল তাই ভাবলাম মিডিয়ামে দিয়ে দেই। ধন্যবাদ।</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3e277c22b200" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[জাভাস্ক্রিপ্ট ইভেন্ট লুপ]]></title>
            <link>https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/%E0%A6%9C%E0%A6%BE%E0%A6%AD%E0%A6%BE%E0%A6%B8%E0%A7%8D%E0%A6%95%E0%A7%8D%E0%A6%B0%E0%A6%BF%E0%A6%AA%E0%A7%8D%E0%A6%9F-%E0%A6%87%E0%A6%AD%E0%A7%87%E0%A6%A8%E0%A7%8D%E0%A6%9F-%E0%A6%B2%E0%A7%81%E0%A6%AA-a1e4cd6f417e?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/a1e4cd6f417e</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[event-loop]]></category>
            <category><![CDATA[ইভেন্ট-লুপ]]></category>
            <category><![CDATA[bangla]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Thu, 01 Nov 2018 06:14:42 GMT</pubDate>
            <atom:updated>2018-11-01T06:24:06.133Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zQCnyoQ3XewNaDAQ" /><figcaption>“people queuing beside Louis Vuitton store” by <a href="https://unsplash.com/@melanie_sophie?utm_source=medium&amp;utm_medium=referral">Melanie Pongratz</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>— আসেন কানে কানে একটা সিক্রেট বলি। ‘<em>জাভাস্ক্রিপ্ট একটি সিঙ্গেল থ্রেডেড ল্যাঙ্গুেজ।’</em></p><p>— কিন্তু, কিন্তু, তাহলে অ্যাসিনক্রোনাস হয় কিভাবে?</p><p>— আরে ভাই, অ্যসিনক্রোনাস হতে হলে মাল্টি-থ্রেডেড হতে হবে এমন কথা কই পাইলেন? লেখা আছে কোথাও?</p><p>—তাহলে এই কোডটা দেখেন। আপনি কি বলতে চান এই দুইটা রিকোয়েস্ট একটা শেষ হওয়ার পর আরেকটা শুরু হবে? পাইথনের মত?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T2AHasUKlfzoyMY3K58LcQ.png" /></figure><p>ধুর মিয়া আপনি কিছু জানেন না। জাভাস্ক্রিপ্ট হইল <em>অ্যাসিনক্রোনাস</em> ল্যাঙ্গুয়েজ।</p><p>— আচ্ছা শোনেন তাহলে। জাভাস্ক্রিপ্ট ইন্জিনগুলো অনেকটা কাউন্টারের মত। আর আমরা যেসব কোড লিখি সেগুলো হল কাস্টমারের মত। ইন্জিনগুলো সেগুলোকে একটি লাইনে দাঁড় করায় তারপর একের পর এক এক্সিকিউট করে। যেমন এই কোডটা দেখুন-</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7zjjT6GdAypWSC6_VVpufg.png" /></figure><p>এখনে কি হবে? প্রথমে তিনটি স্টেটমেন্ট লাইনে দাড়াবে। একের পর এক এক্সিকিউট হবে। তিন নম্বর স্টেটমেন্ট এক্সিকিউট করার সময় দেখবে সেখানে আবার অন্য একটা ফাংশন ১০০ মিলিসেকেন্ড পরে এক্সিকিউট করার কথা বলা হচ্ছে। তো ইন্জিন সেটা নোট করে রাখবে এবং ১০০ মিলিসেকেন্ড পরে সেই ফাংশনটাকে লাইনে ঢুকিয়ে দেবে। কোন পর্যায়েই দুটি স্টেটমেন্ট একসাথে এক্সিকিউট করেবে না। বিশ্বাস না হলে নিচের কোডটি চালিয়ে দেখতে পারেন।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sePj2KyngnZtNKF9bbbYZg.png" /></figure><p>এখানে a, b দুইটা ফাংশনই ০ মিলিসেকেন্ড পরে মানে সাথে সাথে এক্সিকিউট করতে বলা হচ্ছে। a ফাংশনে একটু বড় ক্যালকুলেশন করা হচ্ছে, তাই বেশ কিছুটা সময় লাগছে। জাভাস্ক্রিপ্ট মাল্টিথ্রেডেড হলে a শেষ হওয়ার আগেই b শুরু হয়ে যাওয়ার কথা না? কিন্তু b সব সময়ই a এর পরে শুরু হবে।</p><p>— আচ্ছা। সেটা না হয় বুঝলাম। কিন্তু আমার আগের প্রশ্নের উত্তর কিন্তু পাইনি।</p><p>— এখন কথা হল, ব্রাউজার বা নোড অ্যাপের সব কাজ কিন্তু জাভাস্ক্রিপ্টে হয় না। বরং অনেক কিছুই <em>হোস্ট সিস্টেমে (যেমন- ব্রাউজার) </em>হয়। যখন কোন ajax কল করা হয় তাখন টিসিপি কানেকশন খুলে ডাটা নিয়ে আসার দায়িত্বি হোস্ট সিস্টেমের কাছে চলে যায়। আর জাভাস্ক্রিপ্ট ইন্জিন <em>লাইনের</em> পরবর্তী স্টেটমেন্ট এক্সিকিউট করতে থাকে। ajax এর কাজ শেষ হলে আবার রেজাল্টসহ কলব্যাক লাইনে দাঁড়িয়ে যায়। তখন লাইনে আর কিছু না থাকলে সাথে সাথেই কলব্যাক এক্সিকিউট হবে আর থাকলে সেটা শেষ হওয়ার পর কলব্যাক এক্সিকিউট হবে।</p><p>অন্যান্য ল্যাঙ্গুয়েজের সাথে জাভাস্ক্রিপ্টের পার্থক্যটা হল এর নন-ব্লকিং বৈশিষ্ট্য। মানে কোন সিস্টেম প্রসেস যেমন ajax কল শেষ হওয়ার জন্য অপেক্ষা না করে পরবর্তী কোড এক্সিকিউট করতে শুরু করে।</p><p>এখন হোস্ট সিস্টেম একসাথে কয়টা রিকুয়েস্ট প্রসেস করছে সেটা ডিপেন্ড করবে হোস্টের উপর, কিন্তু জাভাস্ক্রিপ্ট ইন্জিন কখনোই একসাথে একটার বেশি স্টেটমেন্ট প্রসেস করবে না।</p><p>আর এই যে <em>লাইনের</em> কথা বললাম সেটাই হল জাভাস্ক্রিপ্ট ইভেন্ট লুপ।</p><p>— ও আচ্ছা। এখন বুঝলাম। একবার <em>socket.io </em>ব্যবহার করার সময় জানতে ইচ্ছা করছিল একসাথে সর্বোচ্চ কয়টা কানেকশন হ্যান্ডেল করা যাবে। StackOverflow তে দেখেছিলাম, ইন থিওরি মেমরিতে যতটা কানেকশন অবজেক্ট রাখা সম্ভব ততটা! ব্যাপারটা খুব অদ্ভুত লেগেছিল। কিন্তু আসলে ত সবগুলো কানেকশন কখনোই একসাথে হ্যান্ডেল হবে না। বরং একটার পর একটা হ্যান্ডেল হবে।</p><p>— হুমম্।</p><p>— আচ্ছা এইগুলা কি জানার কোন দরকার আছে? এতদিন তো জানতাম না জনেও ভালই চলছিল।</p><p>— অবশ্যই আছে। মনে করুন আপনার কাছে কয়েক লক্ষ অবজেক্টের একটা লিস্ট আছে। এগুলোকে প্রসেস করে একটা রেজাল্ট বের করতে হবে। এখন সবগুলো যদি একসাথে প্রসেস করতে চান তাহলে কিন্তু বেশ কিছু সময় লেগে যাবে। এই সময়টুকুতে জাভাস্ক্রিপ্ট ইন্জিন পুরোপুরি ব্যাস্ত থাকবে, ফলে ব্রাউজারের অন্যান্য ইভেন্টে রেসপন্স করতে পারবে না। ফলে কার্যত ঐ সময়টাতে পেজটা ইরেসপন্সিভ হয়ে থাকবে। যেমনটা এই এক্সাম্পলটাতে দেখতে পাচ্ছেন।এখানে যতক্ষন processList এক্সিকিউট হচ্ছে ততক্ষন পেজটা রেসপন্স করছে না।</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodepen.io%2Fsjsakib%2Fembed%2Fpreview%2FoaKWba%3Fheight%3D600%26slug-hash%3DoaKWba%26default-tabs%3Djs%2Cresult%26host%3Dhttps%3A%2F%2Fcodepen.io&amp;url=https%3A%2F%2Fcodepen.io%2Fsjsakib%2Fpen%2FoaKWba&amp;image=https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fi.cdpn.io%2F2539892.oaKWba.small.0bcf252f-2dd4-469a-b438-2fb43fa19da5.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codepen" width="800" height="600" frameborder="0" scrolling="no"><a href="https://medium.com/media/5978575b67e05eb6c04d55781d731baa/href">https://medium.com/media/5978575b67e05eb6c04d55781d731baa/href</a></iframe><p>এটাকে আমরা এভাবে সমাধান করতে পারি। পুরোটা লিস্ট একবারে প্রসেস না করে, এটিকে ভেঙ্গে ভেঙ্গে প্রসেস করতে পারি। তাহলে লম্বা একটা প্রসেস ইভেন্ট লুপ বেশি সময়ের জন্য ব্লক করে রাখছে না। বরং ছোট ছোট অনেকগুলো প্রসেস লুপে ঢুকছে। ফলে অন্যান্য প্রসেসও (যেমন- চেকবক্সের অনক্লিক) মাঝখানে ঢুকতে পারছে।</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodepen.io%2Fsjsakib%2Fembed%2Fpreview%2FPyMmBZ%3Fheight%3D600%26slug-hash%3DPyMmBZ%26default-tabs%3Djs%2Cresult%26host%3Dhttps%3A%2F%2Fcodepen.io&amp;url=https%3A%2F%2Fcodepen.io%2Fsjsakib%2Fpen%2FPyMmBZ&amp;image=https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fm.cdpn.io%2Fscreenshot-coming-soon-small.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codepen" width="800" height="600" frameborder="0" scrolling="no"><a href="https://medium.com/media/6826dc6cf4f76ff183364fcaf5e81616/href">https://medium.com/media/6826dc6cf4f76ff183364fcaf5e81616/href</a></iframe><p>বিস্তারিত জানতে এখানে দেখতে পারেন। ধন্যবাদ।</p><p><a href="https://github.com/getify/You-Dont-Know-JS/blob/master/async%20%26%20performance/ch1.md">getify/You-Dont-Know-JS</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a1e4cd6f417e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/%E0%A6%9C%E0%A6%BE%E0%A6%AD%E0%A6%BE%E0%A6%B8%E0%A7%8D%E0%A6%95%E0%A7%8D%E0%A6%B0%E0%A6%BF%E0%A6%AA%E0%A7%8D%E0%A6%9F-%E0%A6%87%E0%A6%AD%E0%A7%87%E0%A6%A8%E0%A7%8D%E0%A6%9F-%E0%A6%B2%E0%A7%81%E0%A6%AA-a1e4cd6f417e">জাভাস্ক্রিপ্ট ইভেন্ট লুপ</a> was originally published in <a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE">প্রোগ্রামিং পাতা</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React + Firebase দিয়ে স্টেপ বাই স্টেপ বানিয়ে ফেলুন সিম্পলের মধ্যে গর্জিয়াস চ্যাটরুম]]></title>
            <link>https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/react-firebase-%E0%A6%A6%E0%A6%BF%E0%A7%9F%E0%A7%87-%E0%A6%B8%E0%A7%8D%E0%A6%9F%E0%A7%87%E0%A6%AA-%E0%A6%AC%E0%A6%BE%E0%A6%87-%E0%A6%B8%E0%A7%8D%E0%A6%9F%E0%A7%87%E0%A6%AA-%E0%A6%AC%E0%A6%BE%E0%A6%A8%E0%A6%BF%E0%A7%9F%E0%A7%87-%E0%A6%AB%E0%A7%87%E0%A6%B2%E0%A7%81%E0%A6%A8-%E0%A6%B8%E0%A6%BF%E0%A6%AE%E0%A7%8D%E0%A6%AA%E0%A6%B2%E0%A7%87%E0%A6%B0-%E0%A6%AE%E0%A6%A7%E0%A7%8D%E0%A6%AF%E0%A7%87-%E0%A6%97%E0%A6%B0%E0%A7%8D%E0%A6%9C%E0%A6%BF%E0%A7%9F%E0%A6%BE%E0%A6%B8-%E0%A6%9A%E0%A7%8D%E0%A6%AF%E0%A6%BE%E0%A6%9F%E0%A6%B0%E0%A7%81%E0%A6%AE-6e381f865aea?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/6e381f865aea</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[bangla]]></category>
            <category><![CDATA[firebase]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Sat, 08 Sep 2018 09:25:51 GMT</pubDate>
            <atom:updated>2018-09-08T17:09:08.248Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ytMIcp6uu6UIZpApG1LFYg.png" /><figcaption>Image taken from <a href="https://medium.freecodecamp.org/react-and-firebase-are-all-you-need-to-host-your-web-apps-f7ab55919f53">https://medium.freecodecamp.org/react-and-firebase-are-all-you-need-to-host-your-web-apps-f7ab55919f53</a></figcaption></figure><h4>ফায়ারবেজ কি?</h4><p>ফায়ারবেজ হচ্ছে গুগলের একাটি প্ল্যাটফর্ম যা ডেভেলাপারদের অ্যাপ্লিকেশন ডেভেলাপ করার জন্য বিভিন্ন সার্ভিস দিয়ে থাকে, যেমন অথেনটিকেশন, ডেটাবেজ, স্টোরেজ, হোস্টিং, ক্লাউড ফাংশন ইত্যাদি। এক কথায় একটি অ্যাপ্লিকেশন বানাতে যা যা ইনফ্রাস্ট্রাকচার লাগে সবই। ফায়ারবেজ ব্যবহার করে কোন ব্যাকএন্ড ছাড়াই চমৎকার অ্যাপ্লিকেশন বানানো সম্ভব।</p><p>আজ রিএ্যাক্ট আর ফায়ারবেজ দিয়ে স্টেপ বাই স্টেপ একটি চ্যাটরুম অ্যাপ বানিয়ে ফায়ারবেজ এর মূল সার্ভিসগুলোর সাথে পরিচয় করিয়ে দিতে চেষ্টা করব।এই টিউটরিয়ালে ধরে নেব আপনার রিঅ্যাক্টের উপর মুটামুটি দখল আছে। আপনি অলরেডি ফায়ারবেজ এক্সটপার্ট হলে এড়িয়ে যেতে পারেন। তবে আমি যেহেতু নুব ডেভেলাপার, ভুল ত্রুটিগুলো ধরিয়ে দিলে খুবই উপকার হয়।</p><h4>রিঅ্যাক্ট অ্যাপ</h4><p>প্রথমেই একটি রিঅ্যাক্ট অ্যাপ শুরু করে নিই। node, yarn, create-react-app ইন্সটল করা না থালে গুগল করে ইন্সটল করে নিন। (yarn যদিও জরুরী না। আমি ব্যাক্তিগতভাবে yarn ব্যবহার করি কারণ লোকাল ক্যাশ ব্যবহার করায় yarn অনেক ফাস্ট আর কম ব্যান্ডউইথ খরচ করে।)</p><pre>create-react-app fire-adda<br>cd fire-adda<br>yarn start</pre><p>এখন একটি Room কম্পোনেন্ট তৈরী করে নেব। এর স্টেট এ আপাতত থাকবে messages, currentUser। render মেথডে আমরা মেসেজগুলা রেন্ডার করার পাশাপাশি নতুন মেসেজের জন্য একটা ফরম রেন্ডার করব। ফরম সাবমিট করলে স্টেট এর messagges এ নতুন মেসেজ অ্যাড হবে।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Qpv1BZXh9lUI8n_YV_2-WA.png" /><figcaption>components/Room.js</figcaption></figure><p>এই কম্পোনেন্টটিকে components একটি ফোল্ডার বানিয়ে Room.js নাম দিয়ে রেখে দেব। এখন App.js এ ইমপোর্ট করে রেন্ডার করব।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/958/1*9wEXosVc53m-LZqiJXBfFg.png" /><figcaption>App.js</figcaption></figure><p>index.css ফাইলটিতে এই স্টাইলগুলো দিয়ে দেব।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/938/1*ekUY21WAJ6fq-H5GAf3PLg.png" /><figcaption>index.css</figcaption></figure><p>(আমি ডিজাইনে একেবারেই কাঁচা। শুধু মুটামুটি একটা লুক দেয়ার চেষ্টা করলাম)</p><p>তাহলে মুটামুটি এমন একটা জিনিস পাওয়া গেল।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/426/1*OAa3YBH0jvw3pRdyVuOc1Q.png" /></figure><p>এই পর্যায়ে পুরো প্রজেক্টের কোড কি অবস্থায় আছে তা <a href="https://github.com/sjsakib/fire-adda/tree/step-1">এখানে</a> দেখে নিতে পারেন।</p><h4>রিয়েলটাইম ডেটাবেজ</h4><p>ফায়ারবেজের খেলা শুরু করা যাক। এই পর্যায়ে মেসেজগুলো ফায়ারবেজের রিয়েলটাইম ডেটাবেজে সেভ করে রাখব। প্রথমেই একটি নতুন ফায়ারবেজ প্রজেক্ট ক্রিয়েট করেব নিতে হবে। <a href="https://console.firebase.google.com/u/0/">‍এখান থেকে</a> একটি ফায়ারবেজ প্রজেক্ট তৈরী করে নিই। (প্রথমবার ভিজিট করলে গুগল একাউন্ট সিলেক্ট করতে বলতে পারে।)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/513/1*dAtLiuCKnCvktbpiCbIyWQ.png" /></figure><p>প্রজেক্ট ক্রিয়েট করার পর বামের মেনু থেকে Database সিলেক্ট করে একটি রিয়েলটাইম ডেটাবেজ তৈরী করে নিই।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/996/1*ZTn2cP4FVLnb-Rvy1BEYVw.png" /></figure><p>ডেটাবেজ তৈরী করার সময় test-mode সিলেক্ট করে নিতে হবে।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/668/1*skMgq9t4PZ-Uh9xXj9dqLA.png" /></figure><p>এখন প্রজেক্টে ফায়ারবেজ ইন্সটল করে নেব।</p><pre>yarn add firebase</pre><p>প্রজেক্টের src ডাইরেক্টরিতে firebase.js নামে একটি ফাইল তৈরী করে ঐখানে ফায়ারবেজ কনফিগার করে এক্সপোর্ট করব।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rmF8e3HZ0QBI4SzX3qu0zw.png" /><figcaption>config অবজেক্টটি Project settings &gt; Add firebase to your web app থেকে কপি করে নিতে হবে যেখানে প্রত্যেক প্রজেক্টের apiKey, databaseURL ইত্যাদি থকবে।</figcaption></figure><p>এখন Room.js এ এই ফাইলটি থেকে ফায়ারবেজ ইমপোর্ট করব।Room কম্পোনেন্টের কন্সট্রাক্টরে ফায়ারবেজ ডেটাবেজের একটি ইন্সট্যান্স তৈরী নেব। তারপর sendMessage মেথডে মেসেজগুলো সেভ করতে হবে।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VD6Ni1ZNCNB6mMTVkm-XkQ.png" /><figcaption>Room.js এর চেন্জগুলো</figcaption></figure><p>ফায়ারবেজের রিয়েলটাইম ডেটাবেজগুলো একেকটা বড় json অবজেক্টের মত। আমরা ঐ অবজেক্টের যেকোন ‘path’ আপডেট বা চেন্জ করতে পারি। এখানে /messages পাথ এ নতুন মেসেজগুলা এড করছি। এজন্য /messages পাথ এর রেফারেন্সে push() কল করার মাধ্যমে একটি নতুন অবজেক্ট রেফারেন্স তৈরী করে নিচ্ছি। তারপর ঐ রেফারেন্সে অবজেক্ট ভ্যালু সেট করে দিচ্ছি।</p><p>ডেটাগুলা সেভ হচ্ছে কিনা নিশ্চিত হওয়ার জন্য ফায়ারবেজ কনসোলে ডেটাবেজ সেকশনে দিয়ে দেখে নেয়া যেতে পারে।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/519/1*e9Pw_sTW5dNhKmWGecxHkQ.png" /></figure><p>এই পর্যায়ে আমরা নতুন মেসেজগুলো ডেটাবেজে শুধু সেভ করছি। এখন মেসেজগুলো ডেটাবেজ থেকে লোড করার ব্যবস্থা করতে হবে। Room এর componentDidMount লাইফসাইকেল মেথডে (যা কম্পোনেন্ট মাউন্ট হওয়ার পর মানে dom এ এড হওয়ার পর কল হয়) এই ব্যবস্থা করব।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gYl1Znu8O12N-kVEoJmk9Q.png" /><figcaption>Room এ এই মেথডটি এড করে দিতে হবে</figcaption></figure><p>এখানে আমরা /messages পাথ এ child_added ইভেন্টের জন্য লিসেনার এড করে দিচ্ছি। মনে যখনই এই পাথে কোন নতুন অবজেক্ট অ্যাড হবে আমাদের লিসেনার কল হবে। লিসেনারে আমরা ভ্যালু নিয়ে স্টেট আপডেট করে দিচ্ছি। child_added এর সুবিধা হল এটি শুধু প্রত্যেকবার নতুন অবজেক্ট অ্যাড হওয়ার সময়ই ট্রিগার হয় না বরং লিসেনার অ্যাড করার সাথে সাথে ঐ পাথের পুরনো সবগুলো অবজেক্ট নিয়েও ট্রিগার হয়।</p><p>এখন নতুন একটি উইন্ডোতে অ্যপটি খুলে মেসেজ পাঠিয়ে দেখা যেতে পারে অন্য উইন্ডোতে মেসেজ আসে কি না।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*ZaH0PSEUpxv8lW8pUcrR-Q.gif" /></figure><p>এখন খেয়াল করুন, আমাদের সব নতুন মেসেজগুলো কিন্তু লিসেনারেই স্টেট এ অ্যাড হয়ে যাচ্ছে। তাই sendMessage থেকে স্টেট আপডেট না করলেও চলে।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LHhV_EjBTlNIsiCou6WnjA.png" /></figure><p>এই পর্যায়ে পুরো প্রজেক্টের কোড <a href="https://github.com/sjsakib/fire-adda/tree/step-2">এখানে</a> পাবেন।</p><h4>অথেনটিকেশন</h4><p>অথেনটিকেশন কি? এই পর্যন্ত আমাদের প্রজেক্টের সমস্যা হল সব মেসেজের সেন্ডার হিসেবেই ‘Me’ দেখাচ্ছে। ইচ্ছা করলে একটি টেক্সট ইনপুট দিয়ে ইউজারের নাম নিয়ে সিম্পল একটা সমাধান করা যায়। কিন্তু তাতে করে যে কেউ যে কারো নামে মেসেজ দিতে পারবে। তাই আমাদের প্রত্যেক ইউজার আলাদা আলাদাভাবে চেনা দরকার। সেটাই অথেনটিকেশন। সহজ করে বললে লগইন করার ব্যবস্থাই অথেনটিকেশন। এমনিতে অথেনটিকেশন বেশ একটা ঝামেলার ব্যাপার। তবে ফায়ারবেজ দিয়ে অথেনটিকেশন বেশ সোজা।</p><p>প্রথমেই ফায়ারবেজ কনসোল এর অথেনটিকেশন সেকশন থেকে সাইন ইন মেথড সেটআপ করতে হবে।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/930/1*Py9TXZ8apQcBYBWKXnE9SA.png" /></figure><p>তারপর সাইন-ইন অপশন থেকে গুগল ইন্যাবল করে দিতে হবে যাতে ইউজাররা গুগল একাউন্ট দিয়ে সাইন ইন করতে পারে। চাইলে অন্যান্য প্রভাইডার বা ইমেইল/ফোনও ইন্যাবল করা যেত। আপাতত শুধু গুগল ই রাখছি।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/942/1*dH_o2Ivfrfem_47aBjkMjw.png" /></figure><p>তারপর প্রজেক্টে ফায়ারবেজ ইউআই প্যাকেজ ইন্সটল করে নিতে হবে।</p><pre>yarn add firebaseui</pre><p>এখন App কম্পোনেন্টে দেখতে হবে ইউজার সইনড্-ইন কি না। যদি ইউজার সাইনড্-ইন না হয় তাহলে সাইন ইন করার জন্য আমরা ফায়ারবেজ এর UI দেখাব। আর সইনড্-ইন হলে ইউজারের নাম আর প্রফাইল ফটোর URL currentUser এ রাখব এবং Room রেন্ডার করার সময় প্রপ হিসেবে পাস করে দেব।‌</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WE5PeVWURjdMnmyqjbyqfw.png" /><figcaption>App.js</figcaption></figure><p>আর হ্যাঁ। firebase.js এ firebase/auth ইম্পোর্ট করতে হবে।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/950/1*TeTxFr_L4x6xrW0heAK5mw.png" /><figcaption>firebase.js</figcaption></figure><p>এখন Room এর স্টেটে এ currentUser ডিফল্ট ইউজার না দিয়ে প্রপস থেকে পাওয়া ইউজার দেই।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1012/1*lonkkl-IB3qxM_vDqr8xIg.png" /><figcaption>Room এর constructor</figcaption></figure><p>Room এর রেন্ডার মেথডে message div এ ইউজারের ফটো এড করে দেই</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/974/1*HzYU0X9fMHtRXDqHaZ6p0A.png" /></figure><p>index.css এ এই স্টাইলগুলো এড করে দেই।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/974/1*QsLZB2LLz4wNWvB24LqBLg.png" /></figure><p>এখন শুধু একটা বড় সমস্যা রয়ে গেছে। সেটা হল আমাদের ডেটাবেজের সব ডেটাই ওপেন। চাইলে যে কেউ ফায়ারবেজের রেস্ট এপিআই ব্যবহার করে ডেটাগুলো এক্সেস করতে পারবে, আবার যেকোন মেসেজ এডও করতে পারবে। এই সমস্যা সমাধানের জন্য আমাদের ডেটাবেজে সিকিউরিটি রুল এড করতে হবে।</p><p>ফায়ারবেজ কনসোল থোকে Database &gt; Ruels এ গিয়ে পুরনো রুলগুলো মুছে এই রুলগুলো দিয়ে দেই।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/656/1*3VjRM8O0P0KoEy1EBi0bGA.png" /></figure><p>ফায়াবেজের সিকিউরিটি রুলগুলো পাথ অনুসারে দিতে হয়। এখানে আমারা ফায়াবেজের দেয়া দুটি ভ্যারিয়েবল ব্যবহার করছি। auth: কোন ইউজার যখন ডেটাবেজ থেকে ডেটা পড়ার বা লেখার রিকুয়েস্ট করবে এই ভ্যারিয়েবলে ইউজারের অথরাইজেশন ডেটা থাকবে। যেমন uid বা ইউনিক উজার আইডি ইত্যাদি। newData: ইউজার নতুন ডেটা ক্রিয়েট করতে চাইলে যে ডেটা ক্রিয়েট করতে চাইছে সেটা থাকবে এই ভ্যারিয়েবলে। সে কি ডেটা ক্রিয়েট করতে চাইছে সেটা দেখে আমরা পারমিশন দিতে বা ডিনাই করে দিতে পারব।</p><p>এই রুলগুলোতে আমরা বলে দিচ্ছি auth এ uid যদি null না হয় তাহলে রুট পাথ এ .read পারমিশন ট্রু হবে। মানে ইউজার যদি সাইন্ড ইন হয় তাহলে যেকোন ডেটা পড়তে পারবে। আর নতুন ডেটার /user/uid যদি auth.uid এর সমান হয় তাহলে .write ট্রু হবে। মানে ইউজার যে নতুন মেসেজ এড করতে চাইছে তার ইউজার অবজেক্টের uid যদি সে যে ইউজার হিসেবে রিকুয়েস্ট করছে তার uid এর সমান হয় তাহলেই পারমিশন পাবে অর্থাৎ সব ইউজার শুধু নিজের নামে মেসেজ পাঠাতে পারবে।</p><p>সিকিউরিটি রুলের বিস্তারিত <a href="https://firebase.google.com/docs/database/security/securing-data">এখানে</a> দেখতে পারেন।</p><p>এখন আমাদের ছোট্ট আরেকটা কাজ করতে হবে, যখন স্টেটে কারেন্ট ইউজার রাখছিলাম তখন name photo এর পাশাপাশি uid ও রাখতে হবে।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/838/1*n8x3LIcxW2Zj7aieUIEGUw.png" /><figcaption>App এর কন্সট্রাক্টরে onAuthStateChanged লিসেনারে currentUser আপডেট করার সময় ইউজারের uid সহ আপডেট করতে হবে।</figcaption></figure><p>এখন ডিপ্লয় করার আগে ছোট্ট দুইটা কাজ করব। (আগেই করা দরকার ছিল। সরি!) child_added লিসেনারের আগে একটা লিমিট সেট করে দেব যাতে শুরুতে লাস্ট দশটা মেসেজ শুধু লোড হয়।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eWSe-oQ64Phil_zxFKNC7A.png" /></figure><p>ইনপুটটাতে একটু স্টাইল দেব আর ফন্ট চেন্জ করে Open Sans দেব।</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*laoWPo5bj-Tu5aH5RPfzug.png" /></figure><p>আমাদের প্রজেক্ট মুটামুটি শেষ। আরো বেশ কিছু ইম্প্রভমেন্ট করা যেত। যেমন পুরনো মেসেজ লোড করার ব্যবস্থা করা যেত, প্রত্যেক মেসেজের সাথে ইউজার অবজেক্ট না রেখে শুধু uid রেখে ইউজার ইনফো আলাদাভাবে রাখা যেত ইত্যাদি। এই প্রজেক্টের উদ্দেশ্য ছিল মূলত ফায়ারবেজের সার্ভিসগুলো তুলে ধরা, তাই সেগুলো আপাতত আর করছি না। এই পর্যন্ত কোডগুলো <a href="https://github.com/sjsakib/fire-adda/tree/step-3">এখানে</a> পাবেন।</p><h4>হোস্টিং</h4><p>এমনিতে সাধারণ রিঅ্যাক্ট প্রজেক্ট <a href="https://pages.github.com/">গিটহাব</a> দিয়েই ডিপ্লয় করা যায়। তবে এই প্রজেক্ট যেহেতু ফায়ারবেজের সার্ভিসগুলো দেখানোর জন্যই করা, তাই এটা ফায়ারবেজ দিয়ে ডিপ্লয় করব।</p><p>প্রথমেই ফয়ারবেজের কমান্ডলাইন টুল ইন্সটল করে নিতে হবে।</p><pre>sudo npm -g install firebase-tools</pre><p>ফায়ারবেজে লগিন করতে হবে।</p><pre>sudo firebase login</pre><p>(পারমিশন সংক্রান্ত ঝামেলা এড়াতে sudo ব্যবহার করছি। যদিও ভাল</p><p>তারপর প্রজেক্ট ডাইরেক্টরিতে ফায়ারবেজ কনফিগার করতে হবে।</p><pre>sudo firebase init</pre><p>Which Firebase CLI features do you want to setup for this folder? এর জন্য Hosting সিলেক্ট করুন। What do you want to use as your public directory? এর জন্য build দিন।</p><p>এবার আমাদের প্রজেক্ট বিল্ড করে ডিপ্লয় করতে হবে।</p><pre>yarn build<br>sudo firebase deploy</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/561/1*UCCD7X7A9QgdImKTfm5F5Q.png" /></figure><p>আমার ডিপ্লয় করা সাইটটি <a href="https://fire-adda.firebaseapp.com/">এখানে</a> দেখতে পারেন। আর <a href="https://github.com/sjsakib/fire-adda">এখানে</a> পুরো প্রজেক্টটি আছে। প্রত্যেক স্টেপের কোড আলাদা ব্রাঞ্চে দেয়া আছে।</p><p><a href="https://github.com/sjsakib/fire-adda">sjsakib/fire-adda</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6e381f865aea" width="1" height="1" alt=""><hr><p><a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE/react-firebase-%E0%A6%A6%E0%A6%BF%E0%A7%9F%E0%A7%87-%E0%A6%B8%E0%A7%8D%E0%A6%9F%E0%A7%87%E0%A6%AA-%E0%A6%AC%E0%A6%BE%E0%A6%87-%E0%A6%B8%E0%A7%8D%E0%A6%9F%E0%A7%87%E0%A6%AA-%E0%A6%AC%E0%A6%BE%E0%A6%A8%E0%A6%BF%E0%A7%9F%E0%A7%87-%E0%A6%AB%E0%A7%87%E0%A6%B2%E0%A7%81%E0%A6%A8-%E0%A6%B8%E0%A6%BF%E0%A6%AE%E0%A7%8D%E0%A6%AA%E0%A6%B2%E0%A7%87%E0%A6%B0-%E0%A6%AE%E0%A6%A7%E0%A7%8D%E0%A6%AF%E0%A7%87-%E0%A6%97%E0%A6%B0%E0%A7%8D%E0%A6%9C%E0%A6%BF%E0%A7%9F%E0%A6%BE%E0%A6%B8-%E0%A6%9A%E0%A7%8D%E0%A6%AF%E0%A6%BE%E0%A6%9F%E0%A6%B0%E0%A7%81%E0%A6%AE-6e381f865aea">React + Firebase দিয়ে স্টেপ বাই স্টেপ বানিয়ে ফেলুন সিম্পলের মধ্যে গর্জিয়াস চ্যাটরুম</a> was originally published in <a href="https://medium.com/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A7%8B%E0%A6%97%E0%A7%8D%E0%A6%B0%E0%A6%BE%E0%A6%AE%E0%A6%BF%E0%A6%82-%E0%A6%AA%E0%A6%BE%E0%A6%A4%E0%A6%BE">প্রোগ্রামিং পাতা</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dingulo: Keep track of your days and have a better insight about your life]]></title>
            <link>https://codeburst.io/dingulo-keep-track-of-your-days-and-have-a-better-insight-about-your-life-67b83f9b2bbb?source=rss-13ad3a000340------2</link>
            <guid isPermaLink="false">https://medium.com/p/67b83f9b2bbb</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[lifestyle]]></category>
            <dc:creator><![CDATA[S.j. Sakib]]></dc:creator>
            <pubDate>Tue, 14 Aug 2018 17:42:34 GMT</pubDate>
            <atom:updated>2018-08-28T06:07:39.156Z</atom:updated>
            <content:encoded><![CDATA[<p>Do you think your life sucks? Does it ever happen that you pass a pretty good day but you don’t even notice that? Yeah, we notice only the bad days and think our life sucks.</p><p>I built an android app to help people with that. If you keep that in your phone, it will send you a notification every day at the end of the day and let you label your day like ‘happy’, ‘productive’, ‘stressful’, ‘sad’ etc. You can also write down a note if you want. Later you can see how many and what percentage of your days were, ‘happy’, ‘productive’, ‘stressful’, ‘sad’ and so. And also, you have to think about your day and reflect on your life to answer ‘How was the day?’ everyday. You might start to ask yourself ‘How do I want to live my life? And how am I actually living it?’</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DQx9pY9P75E1coefgdCkHg.png" /></figure><p>You might want to add your own labels with custom modifiers and color. You can do that.</p><p>Finally you can backup your data to your google drive.</p><p>I hope it helps people live a better and positive life.</p><h3>My experience</h3><p>Now I’ll try to write down about a few challenges I faced while developing the app. But before that, I present some screenshots:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vNLCr9xfutdAnlR6u6oqYg.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sSsJbVIQ8hytXxTDXxpGrg.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qLL09mqCYQ4P34TBxc-JPA.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dEnZO2qaFukZ3cmwZ2L44w.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rZ5XZS4-L2wlf0ERE74ikw.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BKUKNT1Fpjg_wJ46Fn8Dmw.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EoQsjUiVS31JoAD71MzwZA.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eokQyr7fVABG7vxvLAc98A.jpeg" /></figure><h4>The decisions</h4><p>I had just learned <a href="https://reactjs.org/">React</a>. I was new to front-end development as well. <a href="https://facebook.github.io/react-native/">React Native</a> was the first choice. But it seemed to me that react-native apps don’t look beautiful out of the box. Styling react-native components seemed cumbersome and I’ve always sucked at designing UIs. I consider <a href="https://flutter.io/">flutter</a>. Flutter seemed a more ‘battery included’ framework and they promise better looking applications!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*Lg9vPOIldjkh5Mz3Z0cobg.jpeg" /></figure><p>Finally gave up flutter considering the learning curve of dart, little support and JSX! JSX is cool, no? Then I saw <a href="https://infinite.red/ignite">Ignite</a>. Something like a battery included version of react-native! But the encounter with ignite was no good. Tried to run a sample of ignite for several hours. Failed. And then ignite includes <a href="https://github.com/ReactTraining/react-router">react-router</a>, <a href="https://redux.js.org/">redux</a>, <a href="https://github.com/rt2zz/redux-persist">redux-persist</a>, redux-saga (what is even that?) and lots of other packages. I don’t need any of them. Not even redux. (Later realized that using redux could be a good idea though)</p><p>Now it was react-native with a UI library. Then got frustrated choosing a UI library. So, finally decided to build it with pure react-native.</p><h4>Not so pure</h4><p>When I started the project with <a href="https://github.com/react-community/create-react-native-app">create-react-native-app</a>, I didn’t realise that it is not pure react-native, rather the set up is built on top of the <a href="https://docs.expo.io/">Expo SDK</a>. It was nice being able to run the app without installing Android SDK.</p><h4>Learning Curves</h4><p>I thought since I know react, I’ll have react-native almost for free. But that is not true, it’s not just using View instead of div and Text instead of p. Getting used to react-native takes some time.</p><h4>Beef with JSX</h4><p>I didn’t know before that, JSX doesn’t remove extra spaces like HTML parsers do.</p><p>Consider this code:</p><pre>&lt;View&gt; &lt;Text&gt;Some text&lt;/Text&gt; &lt;/View&gt;</pre><p>Notice the white spaces around the Text tag. I’d put them so that the code looks a bit better. But JSX thinks I literally want some space character inside the View around the Text. But in react-native string is only allowed inside Text tag. So I was getting a error with long Java stack trace. Googling the error message, I only found out that it is about invalid JSX. In GitHub and StackOverflow, there were hundreds of examples of invalid JSX caused by different reasons. But I was not doing any of them. All I noticed is that, it was happening when I wrap a list of components inside a View. Spent hours and found nothing. Then tried not to wrap them in View, didn’t work, cause I couldn’t style them.</p><p>Finally <a href="https://prettier.io/">prettier</a> saved me! When I prettified the code, I saw that the extra space was being wrapped like {&#39; &#39;}, I’ve seen that before. But never paid attention ¯\_(ツ)_/¯</p><h4>AsycStorage</h4><p>Sometimes the <a href="https://facebook.github.io/react-native/docs/asyncstorage.html">AsyncStorage</a> was never resolving to anything, nor throwing any error. Didn’t find any solution online. Got suggestion to use redux-persist. How is that possible that in a mature project like react-native something import like AsyncStorage doesn’t work at all?</p><h4>Console</h4><p>The expo setup by default logs in the console. But not all logs were not being logged properly. And if I turned on Debug Js remotely, the expo app crashed immediately. For that too, I found no solutions. So, debugging the AsyncStorage problem got even harder.</p><p>After struggling for few days with these, I had to give up the expo setup.</p><h4>Pure again</h4><p>After all that, I started fresh project with react-native init, copied and refactored the code from old project. I thought I would have to configure Babel, Webpack and all the things manually. But luckily I didn’t have to. That was really easy. Configuring Android SDK was not that hard eitehr. I was getting icons with the expo sdk, now I had to install the <a href="https://github.com/oblador/react-native-vector-icons">react-native-vector-icons</a> package.</p><p>And guess what, the AsyncStorage problem was just gone.</p><h4>V8 and JavaScriptCore</h4><p>I noticed that, sometimes the dates were not being displayed properly. Then I discovered that, it was working with remote debugging mode only. That is because the JS codes of react-native is executed in the JavaScriptCore engine normally. But in remote debugging mode, it’s executed in the V8 engine of chrome. And the JavaScriptCore engine doesn’t work well with dates. So the toLocaleDateString function was not working properly. Had to write my own version of that function.</p><h4>The JS way of sorting things out</h4><p>Then I noticed that sorting was not working on non remote debugging mode either. But this time found nothing online. So no one ever experienced sorting issues with JavascriptCore before? TF is happening?</p><p>Well, the problem was in the compare function. This is how I was sorting…</p><pre>tags.sort((t1, t2) =&gt; t1.count &lt; t2.count)</pre><p>This is not the JavaScript way of sorting things. I knew it. But wrote this out of habit. This is the JS way…</p><pre>tags.sort((t1, t2) =&gt; t1.count - t2.count)</pre><p>So, V8 doesn’t mind the first way. But JavaScriptCore gets pissed off.</p><h4>Google Drive API and multipart requests</h4><p>After installing the <a href="https://github.com/react-native-community/react-native-google-signin">react-native-google-signin</a> and making it work with some efforts I thought it’s all done. Now use the drive rest api with the access token and backup/restore all the key value pairs.</p><p>The problem was with multipart/related requests. To upload a file with metadata to google drive, we have to use a multipart post request. In a multipart request, the request is divided in multiple parts. In this case, the first part is used to to send file metadata. A multipart requests looks like this…</p><pre>POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart HTTP/1.1<br>Authorization: Bearer [YOUR_AUTH_TOKEN]<br>Content-Type: multipart/related; boundary=foo_bar_baz<br>Content-Length: [NUMBER_OF_BYTES_IN_ENTIRE_REQUEST_BODY]<br><br>--foo_bar_baz<br>Content-Type: application/json; charset=UTF-8<br><br>{<br>  &quot;name&quot;: &quot;myObject&quot;<br>}<br><br>--foo_bar_baz<br>Content-Type: image/jpeg<br><br>[JPEG_DATA]<br>--foo_bar_baz--</pre><p>Google has api clients to make this sort of requests easier. But since the JS client is based on <em>NodeJS</em>, couldn’t use it with react-native.</p><p>So, first I tried with a simple non multipart request. It worked. Then I tried to construct the body manually. It was not working. I kept on checking and rechecking the syntax. Where to put single newline and where to put double newlines etc. This was frustrating.</p><p>The syntax was correct the whole time. Only I was sending the main data text instead of the constructed body with the data text while sending the request!</p><h3>That&#39;s all</h3><p>As you’ve noticed this article is mainly about my idiocy while developing the app 😁 I hope you enjoyed reading the article and learned something.</p><p>Now install the app and give it a try. If you like it, please help it spread. Share and recommend to your friends and give a ★★★★★ on google play.</p><p>Get the app <a href="https://play.google.com/store/apps/details?id=com.dingulu">here</a>.</p><figure><a href="http://bit.ly/codeburst"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i3hPOj27LTt0ZPn5TQuhZg.png" /></a></figure><blockquote>✉️ <em>Subscribe to </em>CodeBurst’s<em> once-weekly </em><a href="http://bit.ly/codeburst-email"><strong><em>Email Blast</em></strong></a><strong><em>, </em></strong>🐦 <em>Follow </em>CodeBurst<em> on </em><a href="http://bit.ly/codeburst-twitter"><strong><em>Twitter</em></strong></a><em>, view </em>🗺️ <a href="http://bit.ly/2018-web-dev-roadmap"><strong><em>The 2018 Web Developer Roadmap</em></strong></a><em>, and </em>🕸️ <a href="http://bit.ly/learn-web-dev-codeburst"><strong><em>Learn Full Stack Web Development</em></strong></a><em>.</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=67b83f9b2bbb" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/dingulo-keep-track-of-your-days-and-have-a-better-insight-about-your-life-67b83f9b2bbb">Dingulo: Keep track of your days and have a better insight about your life</a> was originally published in <a href="https://codeburst.io/">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>