<?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:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Stupid Simple]]></title><description><![CDATA[Stupid Simple - engineering so simple that sometimes seems stupid]]></description><link>https://stupidsimple.fly.dev/</link><image><url>https://stupidsimple.fly.dev/favicon.png</url><title>Stupid Simple</title><link>https://stupidsimple.fly.dev/</link></image><generator>Ghost 5.30</generator><lastBuildDate>Fri, 01 May 2026 09:50:42 GMT</lastBuildDate><atom:link href="https://stupidsimple.fly.dev/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Building a Kotlin Multiplatform Library for Android and iOS: A Starter Guide]]></title><description><![CDATA[As I embark on a new side project, I've decided to explore (KMM) to create a shared library that will house all business logic. Inspired by the BLoC architecture pattern. The cherry on top? Each platform will still boast native UIs to ensure top-notch, pixel-perfect animations and visuals.]]></description><link>https://stupidsimple.fly.dev/building-a-kotlin-multiplatform-library-for-android-and-ios-a-starter-guide/</link><guid isPermaLink="false">66236d55f5bfec01071f7555</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Swift]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Sat, 20 Apr 2024 07:32:15 GMT</pubDate><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><p>As I embark on a new side project, I&apos;ve decided to explore Kotlin Multiplatform Mobile (KMM) to create a shared library that will house all business logic. This will include components like the database, app state, and network connectivity. Inspired by the BLoC architecture pattern, popular in Flutter, my goal is to adapt this pattern for use in both Kotlin and native iOS and Android environments. The cherry on top? Each platform will still boast native UIs to ensure top-notch, pixel-perfect animations and visuals.</p><h2 id="setting-the-stage">Setting the Stage</h2><p>First, a bit of setup is required. As of now, Android Studio supports KMM through a plugin, but IntelliJ IDEA Ultimate does not. This is an interesting gap in JetBrains&apos; otherwise comprehensive tool support. Regardless, Android Studio will suffice for our needs.</p><h2 id="building-the-library">Building the Library</h2><h3 id="android">Android</h3><p>To create an Android Archive (AAR) file:</p><ul><li>Open the terminal and navigate to the root of your project.</li><li>Run the command:</li></ul><pre><code class="language-bash">./gradlew clean build</code></pre><ul><li>Once the build completes, you can find the AAR file in:</li></ul><pre><code class="language-bash">/{module_name}/build/outputs/aar
</code></pre><p>This AAR file contains all your Android-specific code packaged neatly.</p><h3 id="ios">iOS</h3><p>To build an XCFramework for iOS, which allows the inclusion of binaries for multiple architectures:</p><ul><li>Execute the following command:</li></ul><pre><code class="language-bash">./gradlew clean assembleXCFramework</code></pre><ul><li>Detailed instructions and variations of this command can be found in the <a href="https://kotlinlang.org/docs/multiplatform-build-native-binaries.html#build-xcframeworks">Kotlin Multiplatform documentation</a>.</li><li>The XCFramework will be located in:</li></ul><pre><code class="language-bash">/{module_name}/build/XCFrameworks</code></pre><h2 id="integrating-the-library-into-your-projects">Integrating the Library into Your Projects</h2><h3 id="android-1">Android</h3><ol><li>Place the AAR file within the <code>modules</code> directory at the root of your Android project (e.g., <code>modules/sample_core.aar</code>).</li><li>In your module&#x2019;s <code>build.gradle.kts</code>, add the following dependency:</li></ol><pre><code class="language-kotlin">dependencies {
    implementation(files(&quot;../modules/sample_core.aar&quot;))
}
</code></pre><h3 id="ios-1">iOS</h3><ol><li>Copy the XCFramework into your iOS project&#x2019;s directory.</li><li>Through Xcode, navigate to your project&apos;s settings, then to &quot;Frameworks, Libraries, and Embedded Content.&quot;</li><li>Use the &apos;+&apos; button to add the XCFramework from your local filesystem.</li><li>Import the framework in any Swift or Objective-C class where it&#x2019;s needed.</li></ol><h2 id="conclusion">Conclusion</h2><p>This post covers the fundamental steps to create and integrate a Kotlin Multiplatform library into Android and iOS projects. Upcoming posts will dive deeper into implementing a database, managing network connectivity with KMM, and utilizing the BLoC pattern to handle state across platforms. Stay tuned for more insights and keep experimenting!</p>]]></content:encoded></item><item><title><![CDATA[Unraveling the Mystery: How to Get the Final Link from Google News RSS in TypeScript]]></title><description><![CDATA[Uncover the mystery of Google News RSS links with TypeScript and Cheerio. Learn to navigate redirections, extract hidden URLs, and enhance your web scraping skills. Master the art of unraveling enigmatic links with confidence and precision.]]></description><link>https://stupidsimple.fly.dev/unraveling-the-mystery-how-to-get-the-final-link-from-google-news-rss-in-typescript/</link><guid isPermaLink="false">6547b0d1565d630107ac25ed</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Sun, 05 Nov 2023 15:14:46 GMT</pubDate><content:encoded><![CDATA[<h2 id="introduction">Introduction:</h2><p>Google News RSS feeds are an excellent source of up-to-date information from various domains. However, these feeds often contain links within the Google News domain that do not provide clear information about the destination. To uncover the actual destination of these links, one must navigate through a series of redirections. In this blog post, we will explore how to achieve this using TypeScript, a powerful programming language, and Cheerio, a popular library for parsing HTML and manipulating the DOM. By the end of this post, you&apos;ll be equipped with the knowledge to extract the final destination URL from Google News links with ease.</p><h2 id="getting-started-understanding-the-challenge">Getting Started: Understanding the Challenge</h2><p>When dealing with Google News RSS feeds, you may encounter links like <code>https://news.google.com/articles/12345</code>, which don&apos;t reveal the actual destination. To solve this mystery, we will create a TypeScript function using Cheerio to fetch the Google News article URL buried beneath these ambiguous links.</p><h2 id="the-solution-typescript-and-cheerio-in-action">The Solution: TypeScript and Cheerio in Action</h2><p>Let&apos;s break down the TypeScript code you provided to understand how it works:</p><pre><code class="language-typescript">import { load } from &quot;cheerio&quot;;

export async function getGoogleNewsArticleUrl(feedUrl: string): Promise&lt;string&gt; {
    const response = await fetch(feedUrl);
    if (!response.ok) {
        throw new Error(response.statusText);
    }

    const $ = load(await response.text());
    const newUrl = $(&apos;a[rel=&quot;nofollow&quot;]&apos;).attr(&quot;href&quot;);
    if (newUrl) {
        return newUrl;
    } else {
        throw new Error(&quot;URL not found&quot;);
    }
}</code></pre><h2 id="heres-how-the-function-works">Here&apos;s how the function works:</h2><ol><li><strong>Fetching the Data</strong>: The function takes a <code>feedUrl</code> as input and uses the <code>fetch</code> function to retrieve the HTML content of the given URL.</li><li><strong>Parsing with Cheerio</strong>: The HTML content is loaded into Cheerio, allowing you to use jQuery-like selectors to navigate the DOM tree.</li><li><strong>Extracting the Redirection URL</strong>: The function looks for anchor (<code>&lt;a&gt;</code>) elements with the attribute <code>rel=&quot;nofollow&quot;</code>, which typically represents the ambiguous Google News links. It then extracts the <code>href</code> attribute, which contains the redirection URL.</li><li><strong>Returning the Final URL</strong>: If a redirection URL is found, it is returned. If not, an error is thrown indicating that the URL was not found.</li></ol><h2 id="conclusion-mastering-the-art-of-unraveling-google-news-links">Conclusion: Mastering the Art of Unraveling Google News Links</h2><p>With the provided TypeScript function and the power of Cheerio, you can now confidently tackle Google News RSS links and extract their final destinations. By understanding the structure of the RSS feed and employing the right tools, you can enhance your web scraping and data extraction skills, making you more adept at handling real-world challenges in web development.</p><p>Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[How to Configure Visual Studio Code to Start Build Task on Project Open Automatically]]></title><description><![CDATA[<h3 id="introduction">Introduction:</h3><p>Have you ever found yourself working on a project, only to discover that the changes you made didn&#x2019;t reflect in the application? I recently faced a similar issue while working on a TypeScript project. After spending hours debugging an unexpected problem that didn&#x2019;t seem to</p>]]></description><link>https://stupidsimple.fly.dev/how-to-configure-visual-studio-code-to-automatically-start-build-task-on-project-open/</link><guid isPermaLink="false">65268607565d630107ac25ca</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Wed, 11 Oct 2023 11:27:25 GMT</pubDate><content:encoded><![CDATA[<h3 id="introduction">Introduction:</h3><p>Have you ever found yourself working on a project, only to discover that the changes you made didn&#x2019;t reflect in the application? I recently faced a similar issue while working on a TypeScript project. After spending hours debugging an unexpected problem that didn&#x2019;t seem to exist, I realized the source of my frustration: I had been modifying the source code, but the changes weren&#x2019;t being compiled into the project. It turned out that the compiled version of the project was being used instead of the new one. To avoid this kind of situation in the future, I decided to reconfigure Visual Studio Code to start the build task whenever I opened the project automatically.</p><h3 id="the-problem">The Problem:</h3><p>The root cause of my issue was the manual triggering of the build task in Visual Studio Code. Every time I made changes, I had to remember to start the build process manually. Forgetting to do so resulted in confusion and wasted time. To permanently resolve this problem, I needed a way to ensure that the build task would start automatically whenever I opened the project.</p><h3 id="the-solution">The Solution:</h3><p>The solution to this problem lies in the <code>tasks.json</code> file in your Visual Studio Code project. By configuring this file properly, you can automate the build process to run automatically when you open your project.</p><p>Here&#x2019;s what you need to add to your <code>tasks.json</code> file:</p><pre><code class="language-json">       &quot;runOptions&quot;: {
            &quot;runOn&quot;: &quot;folderOpen&quot;,
        }</code></pre><p>Here is a full example of the tasks.json file:</p><pre><code class="language-json">{
    &quot;version&quot;: &quot;2.0.0&quot;,
    &quot;tasks&quot;: [
        {
            &quot;type&quot;: &quot;typescript&quot;,
            &quot;tsconfig&quot;: &quot;tsconfig.json&quot;,
            &quot;option&quot;: &quot;watch&quot;,
            &quot;problemMatcher&quot;: [
                &quot;$tsc-watch&quot;
            ],
            &quot;group&quot;: {
                &quot;kind&quot;: &quot;build&quot;,
                &quot;isDefault&quot;: true
            },
            &quot;runOptions&quot;: {
                &quot;runOn&quot;: &quot;folderOpen&quot;
            },
            &quot;label&quot;: &quot;tsc: watch - tsconfig.json&quot;
        }
    ]
}</code></pre><p>In this configuration, the crucial addition is the <code>&quot;runOptions&quot;</code> section. By setting <code>&quot;runOn&quot;: &quot;folderOpen&quot;</code>, you instruct Visual Studio Code to automatically start the specified build task whenever the project folder is opened. This eliminates the need for manual intervention and ensures that your changes are always compiled and reflected in the application.</p><h3 id="conclusion">Conclusion:</h3><p>By reconfiguring Visual Studio Code to automatically start the build task on the project open, you can save time, reduce frustration, and avoid unexpected issues caused by outdated or incorrect builds. Taking a few moments to set up this automation can significantly improve your development workflow and make your coding experience much smoother. Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[Implementing a Lightweight Data Repository for RethinkDB: The Power of Direct Access]]></title><description><![CDATA[<p>When it comes to handling databases in your Node.js applications, simplicity, speed, and reliability are key. One database solution that fits these criteria well is RethinkDB, a real-time NoSQL database designed for modern web and mobile applications. Managing your RethinkDB database can be a breeze, especially when you have</p>]]></description><link>https://stupidsimple.fly.dev/implementing-a-lightweight-data-repository-for-rethinkdb-the-power-of-direct-access/</link><guid isPermaLink="false">6522b025565d630107ac25b7</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Sun, 08 Oct 2023 13:37:10 GMT</pubDate><content:encoded><![CDATA[<p>When it comes to handling databases in your Node.js applications, simplicity, speed, and reliability are key. One database solution that fits these criteria well is RethinkDB, a real-time NoSQL database designed for modern web and mobile applications. Managing your RethinkDB database can be a breeze, especially when you have direct access to it without relying on third-party libraries. In this post, we&apos;ll explore the implementation of a Data Repository for RethinkDB and understand why using direct access makes your application easy, lightweight, and future-proof.</p><h3 id="the-beauty-of-direct-access">The Beauty of Direct Access</h3><p>Directly interacting with RethinkDB using native JavaScript driver methods simplifies your application&apos;s structure. It eliminates unnecessary layers of abstraction, ensuring that your codebase remains clean and intuitive. The <code>DatabaseRepository</code> class presented here provides a straightforward interface for common database operations like creating databases and tables, inserting, updating, and deleting records, executing queries, and handling real-time changes.</p><h3 id="code-insight-creating-a-new-database">Code Insight: Creating a New Database</h3><p>Let&apos;s take a look at how easy it is to create a new database using the <code>createDatabaseIfNotExists</code> method:</p><pre><code class="language-javascript">async createDatabaseIfNotExists(name: string) {
    if (this.conn === null) {
        throw new Error(&apos;Connection is null&apos;);
    }

    const dbList = await r.dbList().run(this.conn);
    if (dbList.includes(name)) {
        return;
    }
    await r.dbCreate(name).run(this.conn);
}
</code></pre><p>In this snippet, the function checks if the specified database name already exists. If not, it creates a new database, all with a few lines of code.</p><h3 id="lightweight-and-future-proof-architecture">Lightweight and Future-Proof Architecture</h3><p>One of the major advantages of using direct access is the lightweight nature of your application. By avoiding unnecessary dependencies, your project&apos;s footprint becomes smaller, leading to faster load times and more responsive performance. Moreover, this approach future-proofs your application. As your project evolves, you won&apos;t be tied down by the constraints of third-party libraries. Your code remains adaptable and ready to embrace future changes in technology.</p><h3 id="experience-the-efficiency">Experience the Efficiency</h3><p>Direct access to RethinkDB ensures efficiency not just in terms of code simplicity, but also in runtime performance. Every operation performed through direct access is optimized for speed, making your application more responsive and scalable.</p><h3 id="get-started-with-your-rethinkdb-project">Get Started with Your RethinkDB Project</h3><p>If you&apos;re eager to implement this efficient approach in your Node.js and RethinkDB projects, you&apos;re in luck. The <code>DatabaseRepository</code> class showcased here is part of an autogenerated start template for Node.js and RethinkDB projects. You can find the complete code and more examples on <a href="https://github.com/ltomaszewski/setup-nodejs-project">GitHub</a>.</p><p>Incorporating direct access to RethinkDB in your projects not only streamlines your development process but also ensures a robust, lightweight, and future-proof architecture. Experience the power of simplicity and efficiency in your database interactions by embracing direct access today.</p><p>Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[Handling CLI Arguments in Node.js TypeScript with Object-Oriented Approach]]></title><description><![CDATA[Command Line Interface (CLI) arguments are a fundamental part of many Node.js applications, enabling developers to pass configurations and options during program execution. In this blog post, we'll explore an object-oriented approach to handling CLI arguments in Node.js TypeScript.]]></description><link>https://stupidsimple.fly.dev/handling-cli-arguments-in-node-js-typescript-with-object-oriented-approach/</link><guid isPermaLink="false">65217700565d630107ac256d</guid><category><![CDATA[Solution]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Sat, 07 Oct 2023 15:29:26 GMT</pubDate><content:encoded><![CDATA[<h3 id="introduction">Introduction:</h3><p>Command Line Interface (CLI) arguments are a fundamental part of many Node.js applications, enabling developers to pass configurations and options during program execution. In this blog post, we&apos;ll explore an object-oriented approach to handling CLI arguments in Node.js TypeScript. Let&#x2019;s delve into the code to understand how it efficiently manages CLI configurations using TypeScript features.</p><h3 id="understanding-the-code">Understanding the Code:</h3><p>The provided code snippet demonstrates a TypeScript implementation of handling CLI arguments through an object-oriented paradigm. Let&#x2019;s break down the key components of this code:</p><pre><code class="language-typescript">// Importing the Env enum from the Constants module
import { Env } from &quot;./Constants&quot;;

// Class representing CLI configuration
export class CLIConfiguration {
    readonly arg1: string; // Command line argument 1
    readonly env: Env; // Environment mode (Development or Production)

    // Private constructor to create an instance of CLIConfiguration
    private constructor(arg1: string, env: Env) {
        this.arg1 = arg1;
        this.env = env;
    }

    // Static method to create CLIConfiguration instance from command line arguments
    static fromCommandLineArguments(argv: string[]): CLIConfiguration {
        // Extracting value of arg1 from command line arguments
        const args = argv.find(arg =&gt; arg.startsWith(&apos;--arg1=&apos;))?.split(&apos;=&apos;)[1];
        
        // Checking if production mode flag is present in command line arguments
        const producationMode = argv.find(arg =&gt; arg.includes(&apos;--runmode=producation&apos;));

        if (args) {
            // Determining the environment based on the presence of production mode flag
            const env = producationMode !== undefined ? Env.Prod : Env.Dev;
            // Creating and returning a new CLIConfiguration instance
            return new CLIConfiguration(args, env);
        } else {
            // Throwing an error if arg1 is not provided in the command line arguments
            throw new Error(&quot;Fatal error: Configuration argument not provided.&quot;);
        }
    }
}</code></pre><h2 id="object-oriented-approach">Object-Oriented Approach:</h2><h3 id="encapsulation">Encapsulation:</h3><p>The CLIConfiguration class encapsulates related properties and methods within a class, promoting a cleaner and more organized code structure.</p><h3 id="modularity">Modularity:</h3><p>The <code>fromCommandLineArguments</code> method encapsulates the logic for parsing CLI arguments, promoting modularity and reusability.</p><h3 id="data-abstraction">Data Abstraction:</h3><p>The <code>CLIConfiguration</code> class abstracts away the complexity of parsing and validating CLI arguments, providing a simple interface for accessing configuration details.</p><h3 id="usage-example">Usage Example:</h3><pre><code class="language-typescript">// Extracting command line arguments
const args = process.argv;

// Creating CLIConfiguration object from the extracted CLI arguments
export const configuration: CLIConfiguration = CLIConfiguration.fromCommandLineArguments(args);

// Logging the configuration details
console.log(&quot;Application started with configuration: &quot; + configuration.arg1 + &quot;, environment: &quot; + configuration.env);</code></pre><h3 id="conclusion">Conclusion:</h3><p>By leveraging TypeScript&#x2019;s object-oriented features, the provided code exemplifies a robust and maintainable approach to handling CLI arguments in Node.js applications. Encapsulation, modularity, and data abstraction are key principles demonstrated here, enabling developers to build scalable and readable CLI argument-handling mechanisms.</p><p>This object-oriented approach enhances code organization and readability and facilitates easier testing and future enhancements. By adopting similar practices, developers can ensure their Node.js applications are structured, maintainable, and adaptable to evolving requirements.</p><p>Check out the comprehensive guide for further reading on automating Node.js project setup with a bash script. Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[Automating Node.js Project Setup with Bash Script]]></title><description><![CDATA[<h2 id="introduction">Introduction</h2><p>Setting up a new Node.js project with a well-defined structure, dependencies, and configuration can be a time-consuming task. To streamline this process, we can create a Bash script that automates the project setup. In this blog post, we&apos;ll explore the reasons for creating such a script,</p>]]></description><link>https://stupidsimple.fly.dev/automating-node-js-project-setup-with-bash-script/</link><guid isPermaLink="false">651d57030e0d95010706a8d0</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Wed, 04 Oct 2023 12:15:32 GMT</pubDate><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><p>Setting up a new Node.js project with a well-defined structure, dependencies, and configuration can be a time-consuming task. To streamline this process, we can create a Bash script that automates the project setup. In this blog post, we&apos;ll explore the reasons for creating such a script, its purpose, and go through each feature implemented in the script.</p><h2 id="reasons-for-automation">Reasons for Automation</h2><ol><li><strong>Consistency</strong>: Automation ensures that every project follows the same structure and configuration, leading to consistency across your codebase.</li><li><strong>Efficiency</strong>: Setting up a project manually can take a significant amount of time, especially if you need to repeat the process frequently. Automation saves time and effort.</li><li><strong>Reduced Errors</strong>: Manual setups can lead to configuration errors. Automation reduces the chance of human error by following a predefined, error-free script.</li><li><strong>Rapid Prototyping</strong>: With a quick setup script, you can prototype ideas faster, allowing you to focus on the actual development and testing.</li></ol><h2 id="purpose-of-the-script">Purpose of the Script</h2><p>The purpose of this Bash script is to create a robust foundation for a Node.js project. It includes:</p><ol><li><strong>Directory Structure</strong>: The script sets up a predefined directory structure to organize the project logically.</li><li><strong>Node.js and npm Check</strong>: It checks if Node.js and npm are installed on the system.</li><li><strong>TypeScript Support</strong>: The script ensures TypeScript is globally installed and initializes a TypeScript configuration file.</li><li><strong>Git Repository</strong>: Initializes a Git repository for version control.</li><li><strong>Visual Studio Code Integration</strong>: Creates necessary Visual Studio Code configuration files for tasks and debugging.</li><li><strong>RethinkDB and TypeScript Definitions (Optional)</strong>: Asks the user if they want to install RethinkDB and TypeScript definitions for it.</li></ol><h2 id="features-explained">Features Explained</h2><h3 id="1-directory-structure">1. Directory Structure</h3><p>The script creates a directory structure based on best practices. Here&apos;s a breakdown:</p><ul><li><strong><code>src/</code></strong>: Contains the application source code.</li><li><strong><code>application/</code></strong>: Business logic, services, and other application-specific code.</li><li><strong><code>config/</code></strong>: Configuration files.</li><li><strong><code>domain/</code></strong>: Database models and domain logic.</li><li><strong><code>error-handling/</code></strong>: Custom error handling logic.</li><li><strong><code>infrastructure/</code></strong>: Database connections, repositories, and external integrations.</li><li><strong><code>interfaces/</code></strong>: API routes, controllers, middlewares, and other interface-related code.</li></ul><h3 id="2-typescript-configuration">2. TypeScript Configuration</h3><p>The script sets up TypeScript support, creating a <code>tsconfig.json</code> file with predefined compiler options for a smooth TypeScript development experience.</p><h3 id="3-git-repository-initialization">3. Git Repository Initialization</h3><p>The script initializes a Git repository in the project folder, allowing for version control and collaboration.</p><h3 id="4-visual-studio-code-integration">4. Visual Studio Code Integration</h3><p>The script creates <code>.vscode</code> directory with <code>tasks.json</code> and <code>launch.json</code> configurations. These files enable running TypeScript compilation tasks and debugging inside Visual Studio Code.</p><h3 id="5-rethinkdb-and-typescript-definitions-optional">5. RethinkDB and TypeScript Definitions (Optional)</h3><p>The script asks the user if they want to install RethinkDB. If chosen, it installs RethinkDB and TypeScript definitions for RethinkDB. This ensures a seamless integration with RethinkDB while writing TypeScript code.</p><h2 id="conclusion">Conclusion</h2><p>By automating the Node.js project setup, developers can save valuable time, maintain consistency, and focus on the core aspects of development rather than spending time on repetitive and error-prone tasks. This script provides a robust foundation for any Node.js project, enabling developers to kickstart their projects efficiently and effortlessly. Remember to customize the script according to your specific project requirements, and happy coding!</p><h2 id="final-script">Final Script</h2><p>The final version of the Bash script discussed in this blog post can be found on GitHub:</p><p><a href="https://github.com/ltomaszewski/setup-nodejs-project/blob/master/setup-nodejs-project.sh"><strong>GitHub Repository: setup-nodejs-project.sh</strong></a></p><p>Feel free to explore the script, modify it according to your needs, and use it to automate your Node.js project setups. Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[Troubleshooting Network Speed Limitations: My Journey with Zimaboard 432 and OpenWRT x86]]></title><description><![CDATA[<p>Recently, I encountered an issue with my Zimaboard 432, equipped with openWRT x86 software, which I had purchased to serve as my router for multi-gigabit WAN connections. My Realtek RTL8111 NIC delivered a throughput of approximately 1.3 Gbps, significantly lower than the expected 2.5 Gbps LAN speed. Although</p>]]></description><link>https://stupidsimple.fly.dev/troubleshooting-network-speed-limitations-my-journey-with-zimaboard-432-and-openwrt-x86/</link><guid isPermaLink="false">6472309549c1710210d5f32a</guid><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Sat, 27 May 2023 16:33:47 GMT</pubDate><content:encoded><![CDATA[<p>Recently, I encountered an issue with my Zimaboard 432, equipped with openWRT x86 software, which I had purchased to serve as my router for multi-gigabit WAN connections. My Realtek RTL8111 NIC delivered a throughput of approximately 1.3 Gbps, significantly lower than the expected 2.5 Gbps LAN speed. Although implementing packet streaming and hardware offloading allowed me to increase the speed to 1.4 Gbps marginally, it remained significantly below the desired threshold.</p><p>Seeking a solution, I painstakingly reviewed countless posts and forum threads addressing openWRT speed limitations, but to no avail. My breakthrough came from a Reddit discussion, where I found several users criticizing Realtek NICs due to their subpar drivers. This convinced me to try switching to an Intel NIC.</p><p>With high hopes, I purchased a dual-port Intel NIC and connected it to my Zimaboard via a PCIe slot. Disappointingly, the improvement was marginal, with the speed topping at around 1.5 Gbps, with none of my tweaks boosting the performance further. However, I did notice a significant change in CPU utilization.</p><p>Desperate for a solution and to achieve full performance, I decided to reconfigure my setup. I connected the WAN to the Intel NIC via PCIe, and the LAN via a USB 2.5 Gbps NIC. The result was promising - I saw speeds reach about 1.8 Gbps.</p><p>I was almost there, but one final hurdle remained. To squeeze the last bit of performance out of my setup, I forced the CPU to work at its top frequency using the command:</p><pre><code class="language-bash">for a in /sys/devices/system/cpu/cpufreq/policy*/scaling_governor; do echo performance &gt; $a; done
</code></pre><p>Much to my delight, this last measure proved successful. The full throughput of 2.5 Gbps was finally achieved! My journey of troubleshooting network speed limitations was arduous but ultimately rewarding.</p><p>This experience underscored the importance of comprehensive hardware and software knowledge in navigating the complex landscape of network configurations. I hope this account may be a resource for others facing similar challenges in optimizing their network speeds.</p>]]></content:encoded></item><item><title><![CDATA[Creating an OpenWRT USB Stick for Zimaboard: A Step-by-Step Guide]]></title><description><![CDATA[<p>If you&apos;re looking to create an OpenWRT USB stick for your Zimaboard, you&apos;ve come to the right place. This tutorial will guide you through the process, using a Linux environment, the &apos;dd&apos; tool, and ensuring that the full disk space is utilizable.</p><p><strong>Step 1:</strong></p>]]></description><link>https://stupidsimple.fly.dev/creating-an-openwrt-usb-stick-for-zimaboard-a-step-by-step-guide/</link><guid isPermaLink="false">6467f53249c1710210d5f30f</guid><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Fri, 19 May 2023 22:18:06 GMT</pubDate><content:encoded><![CDATA[<p>If you&apos;re looking to create an OpenWRT USB stick for your Zimaboard, you&apos;ve come to the right place. This tutorial will guide you through the process, using a Linux environment, the &apos;dd&apos; tool, and ensuring that the full disk space is utilizable.</p><p><strong>Step 1: Setting Up the Linux Environment</strong></p><p>Before we can begin, you need to have a Linux environment ready. Any popular distribution like Ubuntu, Debian, or CentOS will work perfectly. Ensure your system is up to date using your distribution&apos;s package manager.</p><p><strong>Step 2: Download the OpenWRT Image</strong></p><p>Visit the OpenWRT download page and locate the latest version for the Zimaboard. As Zimaboard uses an x86/64bit architecture, choose an image compatible with this architecture. Download the image to your Linux machine.</p><p><strong>Step 3: Decompressing the Image</strong></p><p>After the image has been downloaded, we need to decompress it. Navigate to the directory where the file was downloaded and use the following command:</p><p><code>gunzip &lt;filename&gt;</code></p><p>Replace <code>&lt;filename&gt;</code> with the name of the file you downloaded. For instance, if you have downloaded the file &apos;openwrt-22.03.2-x86-64-generic-ext4-combined.img.gz&apos;, the command would be:</p><p><code>gunzip openwrt-22.03.2-x86-64-generic-ext4-combined.img.gz</code></p><p>This command will decompress the image and you&apos;ll end up with &apos;openwrt-22.03.2-x86-64-generic-ext4-combined.img&apos; ready to be flashed onto your USB stick.</p><p><strong>Step 4: Identifying Your Disk</strong></p><p>Use the <code>lsblk</code> command to display all disks connected to your system. This command will provide a list of all storage devices, making it easier to identify the one you&apos;ll be using:</p><p><code>lsblk</code></p><p><strong>Step 5: Flashing the Disk with the OpenWRT Image</strong></p><p>Once you&apos;ve identified the correct disk, you can flash the OpenWRT image onto it using the &apos;dd&apos; tool. In the command below, replace &quot;openwrt-22.03.2-x86-64-generic-ext4-combined.img&quot; with the filename of your OpenWRT image and &quot;/dev/sda&quot; with your disk identifier:</p><p><code>dd if=openwrt-22.03.2-x86-64-generic-ext4-combined.img of=/dev/sda bs=4M; sync;</code></p><p><strong>Step 6: Resizing the Disk to Use Full Capacity</strong></p><p>By default, OpenWRT doesn&apos;t use the full disk space. But you can adjust this by resizing the partition. First, verify your disk again with <code>lsblk</code>.</p><p>Next, install the &apos;parted&apos; tool, which we will use for resizing. On Debian-based distributions, you can use:</p><p><code>sudo apt-get install parted</code></p><p>Use &apos;parted&apos; to print your disk layout:</p><p><code>parted /dev/sda print</code></p><p>This command will show you two partitions. The first one is used for booting, while the second one is what we want to resize. Resize the second partition to use the full available space with the command below. In this case, we&apos;re resizing it to 16GB:</p><p><code>parted /dev/sda resizepart 2 16G</code></p><p>Check your result by printing the disk layout again with <code>parted /dev/sda print</code>.</p><p><strong>Step 7: Resizing the Filesystem</strong></p><p>The final step is to resize the filesystem. Execute the following command:</p><p><code>resize2fs /dev/sda2</code></p><p>Congratulations! You have successfully created an OpenWRT USB stick for Zimaboard that utilizes the full disk space. This USB stick can be used as a live boot device or for installing OpenWRT onto other systems.</p>]]></content:encoded></item><item><title><![CDATA[RethinkDB on Mac Mini M1 - Install script]]></title><description><![CDATA[<p>Over the past 12 months, I have been working on a Proof of Concept for automative trading software. After developing a few prototypes, it&apos;s time to create a single tool that makes it easier to trade, analyze data, and keep track of everything. The first step in this</p>]]></description><link>https://stupidsimple.fly.dev/rethinkdb-on-mac-mini-m1-install-script/</link><guid isPermaLink="false">643c271149c1710210d5f2b6</guid><category><![CDATA[Solution]]></category><category><![CDATA[Algorithmic Trading]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Sun, 16 Apr 2023 17:04:53 GMT</pubDate><content:encoded><![CDATA[<p>Over the past 12 months, I have been working on a Proof of Concept for automative trading software. After developing a few prototypes, it&apos;s time to create a single tool that makes it easier to trade, analyze data, and keep track of everything. The first step in this process is to use RethinkDB as the backbone for our data storage and management. In this blog post, I will provide a ready-to-use script to install RethinkDB and give a walkthrough.</p><h2 id="script-walkthrough">Script Walkthrough:</h2><p>This script is designed for macOS and uses Homebrew as the package manager. It automates the installation and configuration of RethinkDB on your system. Let&apos;s break down the steps involved in the script:</p><ol><li>Define the RethinkDB data directory path in the <code>DB_PATH</code> variable. This is where the database files will be stored.</li><li>Check if Homebrew is installed on the system. If not, the script will install Homebrew automatically.</li><li>Install RethinkDB using Homebrew by running. <code>brew install rethinkdb</code></li><li>Stop any running RethinkDB service with <code>brew services stop rethinkdb</code></li><li>Adjust the RethinkDB configuration file. The script creates a backup of the original configuration file, modifies the data directory path, and changes the network bind address to allow connections from the local network. This will make it possible to connect to the RethinkDB server from other devices in the same network.</li><li>Change the ownership of the RethinkDB data directory and log file to the current user and the wheel group. This step ensures that the current user can manage the RethinkDB files.</li><li>Set RethinkDB to autostart on boot by running <code>brew services start rethinkdb</code>. This command also starts the RethinkDB service immediately. The <code>brew services list</code> command shows the status of the RethinkDB service.</li><li>Finally, the script unsets the local <code>DB_PATH</code> variable to clean up the environment.</li></ol><p>After running this script, RethinkDB will be installed, configured, and set to start automatically whenever your system boots up. With RethinkDB as the backbone</p><pre><code class="language-bash">#!/bin/bash

# 1. Set directory path to a local property
DB_PATH=/Users/lukasztomaszewski/Documents/server2.0/database

# 2. Check if Homebrew is installed
if ! command -v brew &amp;&gt; /dev/null
then
    echo &quot;Homebrew is not installed. Installing now...&quot;
    /bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;
fi

# 3. Install RethinkDB with Homebrew
echo &quot;Installing RethinkDB...&quot;
brew install rethinkdb

# 4. Stop any running RethinkDB service
echo &quot;Stopping RethinkDB service...&quot;
brew services stop rethinkdb

# 5. Adjust RethinkDB configuration
echo &quot;Adjusting RethinkDB configuration...&quot;
cp /opt/homebrew/etc/rethinkdb.conf /opt/homebrew/etc/rethinkdb.conf.backup
sed -e &quot;s|directory=/opt/homebrew/var/rethinkdb|directory=$DB_PATH|&quot; \
    -e &apos;s|# bind=127.0.0.1|bind=all|&apos; \
    /opt/homebrew/etc/rethinkdb.conf.backup &gt; /opt/homebrew/etc/rethinkdb.conf

# 6. Change ownership of RethinkDB data directory and log file
echo &quot;Changing ownership of RethinkDB data directory and log file...&quot;
sudo chown -R $USER:wheel $DB_PATH /opt/homebrew/var/rethinkdb

# 7. Set RethinkDB to autostart on boot
echo &quot;Setting RethinkDB to autostart on boot...&quot;
brew services start rethinkdb
brew services list

# 8. Unset local property
unset DB_PATH
</code></pre><p></p>]]></content:encoded></item><item><title><![CDATA[How to disable system log in Xcode]]></title><description><![CDATA[<p>To disable system logs in Xcode, perform the following steps:</p><ol><li>In Xcode, go to <code>&quot;Window&quot; &gt; &quot;Devices and Simulators&quot;</code></li><li>Select the device or simulator you want to disable logs for.</li><li>In the device&apos;s or simulator&apos;s detail view, click on the <code>Gear</code> icon</li></ol>]]></description><link>https://stupidsimple.fly.dev/how-to-disable-system-log-in-xcode/</link><guid isPermaLink="false">63d9089749c1710210d5f29d</guid><category><![CDATA[Swift]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Tue, 31 Jan 2023 12:26:19 GMT</pubDate><content:encoded><![CDATA[<p>To disable system logs in Xcode, perform the following steps:</p><ol><li>In Xcode, go to <code>&quot;Window&quot; &gt; &quot;Devices and Simulators&quot;</code></li><li>Select the device or simulator you want to disable logs for.</li><li>In the device&apos;s or simulator&apos;s detail view, click on the <code>Gear</code> icon at the bottom left corner.</li><li>Select <code>Edit Scheme</code>.</li><li>Under <code>Run &gt; Arguments</code>, add the argument <code>OS_ACTIVITY_MODE</code> with a value of <code>disable</code>.</li><li>Close the scheme editor and run your app again. System logs should now be disabled.</li></ol>]]></content:encoded></item><item><title><![CDATA[npm install with Realm hang - Solution]]></title><description><![CDATA[<p>When installing Realm via npm, some users may experience an issue where the npm installation process hangs. A problem with the analytics can cause this that Realm sends during installation.</p><p>One solution to this issue is to disable the analytics during installation. To do this, you can use the command</p>]]></description><link>https://stupidsimple.fly.dev/npm-install-with-realm-hang/</link><guid isPermaLink="false">63d1710749c1710210d5f285</guid><category><![CDATA[Solution]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Wed, 25 Jan 2023 18:14:01 GMT</pubDate><content:encoded><![CDATA[<p>When installing Realm via npm, some users may experience an issue where the npm installation process hangs. A problem with the analytics can cause this that Realm sends during installation.</p><p>One solution to this issue is to disable the analytics during installation. To do this, you can use the command <code>REALM_DISABLE_ANALYTICS=1 npm install</code>. This sets the environment variable <code>REALM_DISABLE_ANALYTICS</code> to 1, which tells Realm to skip sending analytics during installation.</p><p>It&apos;s important to note that disabling analytics will not affect the functionality of Realm. It will only prevent analytics from being sent during the installation process. This can help to resolve the issue of npm hanging during the installation of Realm.</p><p>To install Realm via npm without any issues, it is best to use the command <code>REALM_DISABLE_ANALYTICS=1 npm install</code> instead of the usual `npm install` command.</p>]]></content:encoded></item><item><title><![CDATA[How to transform array to dictionary in Swift]]></title><description><![CDATA[<p>In Swift, you can use the <code>map</code> method to transform an array into a new array of the same size, where a provided closure has changed each element. To convert an array to a dictionary, you can use the <code>reduce</code> method. Here&apos;s an example of how to map</p>]]></description><link>https://stupidsimple.fly.dev/how-to-map-array-to-map-in-swift/</link><guid isPermaLink="false">63ce564e994f2102125e4972</guid><category><![CDATA[Swift]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Sun, 22 Jan 2023 23:43:00 GMT</pubDate><content:encoded><![CDATA[<p>In Swift, you can use the <code>map</code> method to transform an array into a new array of the same size, where a provided closure has changed each element. To convert an array to a dictionary, you can use the <code>reduce</code> method. Here&apos;s an example of how to map an array of integers to a dictionary where the key is the integer, and the value is its double:</p><pre><code class="language-swift">let integers = [1, 2, 3, 4, 5]
let doubled = integers.reduce(into: [:]) { $0[$1] = $1 * 2 }
print(doubled)  // [1: 2, 2: 4, 3: 6, 4: 8, 5: 10]</code></pre><p>Or you can use the <code>Dictionary</code> init method like this:</p><pre><code class="language-swift">let array = [1, 2, 3, 4, 5]
let dictionary = Dictionary(uniqueKeysWithValues: array.map { ($0, $0 * 2) })
print(dictionary) // [1: 2, 2: 4, 3: 6, 4: 8, 5: 10]</code></pre><p>You can also use <code>zip</code> method to map array to dictionary</p><pre><code class="language-swift">let array = [1, 2, 3, 4, 5]
let keys = array
let values = array.map { $0 * 2 }
let dictionary = Dictionary(uniqueKeysWithValues: zip(keys, values))</code></pre>]]></content:encoded></item><item><title><![CDATA[How to create node.js app with TradingView integration]]></title><description><![CDATA[<p>Here is a step-by-step guide on how to create a simple Node.js application that uses the <a href="https://github.com/Mathieu2301/TradingView-API">&quot;TradingView-API&quot; GitHub repository</a> as a dependency:</p><ol><li>Make <strong>sure you have Node.js and npm</strong> (Node Package Manager) installed on your system. You can check if you have them installed by running</li></ol>]]></description><link>https://stupidsimple.fly.dev/how-to-create-node-js-application-that-connect-to-tradingview/</link><guid isPermaLink="false">63cba770994f2102125e4910</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Algorithmic Trading]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Fri, 20 Jan 2023 22:07:00 GMT</pubDate><content:encoded><![CDATA[<p>Here is a step-by-step guide on how to create a simple Node.js application that uses the <a href="https://github.com/Mathieu2301/TradingView-API">&quot;TradingView-API&quot; GitHub repository</a> as a dependency:</p><ol><li>Make <strong>sure you have Node.js and npm</strong> (Node Package Manager) installed on your system. You can check if you have them installed by running the commands <code>node -v</code> and <code>npm -v</code> in the terminal.</li></ol><p>2. Create a <strong>new directory</strong> for your project and navigate to it in the terminal.</p><p>3. <strong>Initialize</strong> a new Node.js project by running the command <code>npm init</code> in the terminal. This will create a package.json file in your project directory.</p><p>4. <strong>Install</strong> the &quot;TradingView-API&quot; <strong>package</strong> from GitHub by running the following command in the terminal:</p><pre><code class="language-bash">npm install Mathieu2301/TradingView-API</code></pre><p><strong>This will install the package as a dependency in your project.</strong></p><p>5. Create a new file called <code>SimpleChart.js</code> in your project directory. This file will contain the main logic of your application.</p><p>6. <strong>Open</strong> the <code>SimpleChart.js</code> file in a text editor and import the &quot;TradingView-API&quot; package at the top of the file by using the following line of code:</p><pre><code class="language-bash">const TradingView = require(&apos;@mathieuc/tradingview&apos;);</code></pre><p>7. Use the functions and classes of the package in your code as you need. Here is example of use to get the most recent Bitcoin price from Binance:</p><pre><code class="language-javascript">const TradingView = require(&apos;@mathieuc/tradingview&apos;);

const client = new TradingView.Client();
const chart = new client.Session.Chart(); // Init a Chart session

chart.setMarket(&apos;BINANCE:BTCBUSD&apos;, { // Set the market
  timeframe: &apos;15&apos;,
  range: 20000
});

chart.onError((...err) =&gt; { // Listen for errors (can avoid crash)
  console.error(&apos;Chart error:&apos;, ...err);
  // Do something...
});

chart.onSymbolLoaded(() =&gt; { // When the symbol is successfully loaded
  console.log(`Market &quot;${chart.infos.description}&quot; loaded !`);
});

chart.onUpdate(() =&gt; { // When price changes
  if (!chart.periods[0]) return;
  console.log(`[${chart.infos.description}]: ${chart.periods[0].close} ${chart.infos.currency_id}`);
});</code></pre><p>9. Once you have finished writing your code, you can run it by using the command. <code>node SimpleChart.js</code></p><p>10. If you want to share your project with others or deploy it to a production environment, you can use the <code>npm pack</code> command to create a tarball of your project, which can then be distributed and installed using <code>npm install &lt;tarball-file&gt;</code></p><p>Please note that the package you are trying to install is not officially supported by TradingView, it could be that it&apos;s not working properly or is no longer maintained. Make sure to check the Github repository and read the README file to get more information about how to use the package.</p>]]></content:encoded></item><item><title><![CDATA[How to become a profitable trader - Step by Step]]></title><description><![CDATA[So let's put down points to follow to become a profitable trader.]]></description><link>https://stupidsimple.fly.dev/how-to-become-profitable-trader-step-by-step/</link><guid isPermaLink="false">63caa647994f2102125e48fe</guid><category><![CDATA[Algorithmic Trading]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Fri, 20 Jan 2023 14:34:43 GMT</pubDate><content:encoded><![CDATA[<ol><li>Develop a trading plan: A trading plan should include your investment goals, risk management strategy, and the specific methods you will use to analyze the market and make trades.</li><li>Educate yourself: Learn about different trading strategies, market analysis techniques, and the risks involved in trading. Keep updated on current economic and political events that may impact the markets.</li><li>Use a demo account: Practice trading in a simulated environment before risking real money. This will allow you to test your strategies and get a feel for the market without the risk of losing money.</li><li>Start with a small investment: When you&apos;re first starting out, it&apos;s best to invest a small amount of money until you become more comfortable with the markets and your trading strategies.</li><li>Use stop-loss orders: A stop-loss order is an order that automatically closes a trade when it reaches a certain price level, limiting your potential loss.</li><li>Diversify your portfolio: Spread your investments across multiple markets and asset classes to reduce your overall risk.</li><li>Keep a trading journal: Record your trades, including the reasons for your decisions and the outcomes. This will help you identify and learn from your mistakes.</li><li>Continuously evaluate and adjust your strategy: Regularly review your trading performance and make adjustments to your strategy as needed.</li></ol><p>It is worth noting that, trading can be a high-risk activity and it&apos;s important to have realistic expectations, keep emotions in check and not to invest more than you can afford to lose. It is always recommended to consult a financial advisor before making any investment decisions.</p>]]></content:encoded></item><item><title><![CDATA[How to calculate EMA in Swift]]></title><description><![CDATA[EMA gives more weight to recent price data, helping traders quickly identify trends and respond to changing market conditions.]]></description><link>https://stupidsimple.fly.dev/how-to-calculate-ema-in-swift/</link><guid isPermaLink="false">63c8f12a994f2102125e485e</guid><category><![CDATA[Algorithmic Trading]]></category><category><![CDATA[Swift]]></category><category><![CDATA[Solution]]></category><dc:creator><![CDATA[Lukasz Tomaszewski]]></dc:creator><pubDate>Wed, 18 Jan 2023 10:09:34 GMT</pubDate><content:encoded><![CDATA[<p>To calculate the Exponential Moving Average (EMA) in Swift, you can use the following formula:</p><p><code>EMA = (current_price * k) + (previous_EMA * (1 - k))</code></p><p>Where <code>current_price</code> is the most recent price point, <code>previous_EMA</code> is the previous period&apos;s EMA, and <code>k</code> is the smoothing constant. This constant is calculated as <code>2 / (n + 1)</code>, where <code>n</code> is the number of periods in the EMA.</p><p>Here is some sample code to calculate a 10-period EMA:</p><pre><code class="language-swift">let data = [3.0, 4.0, 5.0, 4.5, 4.0, 5.5, 6.0, 5.5, 5.0, 4.5]
let n = 10
let k = 2 / Double(n + 1)
var ema = data[0]

for i in 1..&lt;data.count {
    ema = (data[i] * k) + (ema * (1 - k))
}

print(ema)</code></pre><p>You can also use the <code>reduce</code> function to calculate the EMA.</p><pre><code class="language-swift">let k = 2 / Double(n + 1)
let ema = data.suffix(n).reduce(data.first!) { (prev, curr) in (curr * k) + (prev * (1 - k)) }</code></pre><p>In this code snippet, <code>data</code> is an array of Double containing the trading data, <code>n</code> is the number of periods in the EMA, <code>k</code> is the smoothing constant, <code>ema</code> is the calculated EMA.</p><p>Keep in mind that the first EMA value is typically the SMA of the first n periods, and then the EMA is calculated based on that value.</p>]]></content:encoded></item></channel></rss>