<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Christopher C. Johnson</title>
    <description>The latest articles on Forem by Christopher C. Johnson (@programazing).</description>
    <link>https://forem.com/programazing</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F400%2F59e06fa3-6abd-40c1-8e52-a43497fe3ca5.jpg</url>
      <title>Forem: Christopher C. Johnson</title>
      <link>https://forem.com/programazing</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/programazing"/>
    <language>en</language>
    <item>
      <title>Fluent Assertions 8: Corporate License Update</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Fri, 17 Jan 2025 15:28:28 +0000</pubDate>
      <link>https://forem.com/programazing/fluent-assertions-8-corporate-license-update-1ml</link>
      <guid>https://forem.com/programazing/fluent-assertions-8-corporate-license-update-1ml</guid>
      <description>&lt;p&gt;In the ever-changing world of .NET development, testing frameworks are vital in ensuring code quality and reliability. One framework that has gained significant popularity is &lt;a href="https://fluentassertions.com/" rel="noopener noreferrer"&gt;Fluent Assertions&lt;/a&gt;. However, recent developments have caused concerns within the .NET community, prompting developers to rethink their testing strategies.&lt;/p&gt;

&lt;p&gt;Fluent Assertions is well-known for its expressive and readable syntax, making it a favorite among .NET developers for writing clear and concise unit tests. Its intuitive API allows for natural, language-like assertions, which enhance the understandability and maintainability of test code. Many teams have relied on Fluent Assertions for everything from simple equality checks to complex object comparisons.&lt;/p&gt;

&lt;p&gt;Nonetheless, the recent announcement of Fluent Assertions 8 has stirred controversy and concern among its users. Introducing a new licensing model for commercial use has led many developers and organizations to reassess their testing approaches. This unexpected change has not only raised questions about the future of the library but also sparked a broader discussion about the sustainability of open-source projects in the .NET ecosystem.&lt;/p&gt;

&lt;p&gt;As we explore the details of this situation, we will examine the implications of the new licensing model, community reactions, and potential alternatives for developers who depend on Fluent Assertions in their projects. Whether you are a long-time library user or are considering it for your next project, this article will provide valuable insights to help you navigate these changes and make informed decisions about your testing strategy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Licensing Model
&lt;/h2&gt;

&lt;p&gt;The introduction of Fluent Assertions 8 brings with it a significant change in the library's licensing structure. This new model represents a departure from the previous open-source approach and has important implications for developers and organizations using the framework.&lt;/p&gt;

&lt;p&gt;Under the new licensing model introduced with little fanfare via a &lt;a href="https://github.com/fluentassertions/fluentassertions/commit/df7e9bf8305ef5e26ae58fe4142f8d1b6c4fc4af" rel="noopener noreferrer"&gt;pull request&lt;/a&gt;, Fluent Assertions now belongs to &lt;a href="https://xceed.com/" rel="noopener noreferrer"&gt;Exceed Software&lt;/a&gt;. The most notable change is that commercial use of Fluent Assertions 8 requires a paid license. This shift means businesses and developers using the library in commercial projects must purchase a license to continue using the latest version.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://xceed.com/products/unit-testing/fluent-assertions/" rel="noopener noreferrer"&gt;new commercial license&lt;/a&gt; costs $129.95 per developer per year. This pricing structure impacts organizations, especially those with larger development teams or multiple projects utilizing Fluent Assertions.&lt;/p&gt;

&lt;p&gt;It's important to note that the new licensing model does not affect all users equally. Fluent Assertions 8 remains free for non-commercial use, including open-source projects. This distinction allows hobbyists, students, and open-source contributors to continue using the library without incurring costs.&lt;/p&gt;

&lt;p&gt;Introducing this new licensing model significantly shifts the Fluent Assertions ecosystem. It raises questions about the long-term sustainability of open-source projects and the balance between maintaining free access for the community while ensuring financial viability for the project's continued development and maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Reaction and Concerns
&lt;/h2&gt;

&lt;p&gt;The announcement of Fluent Assertions 8's licensing change has sparked significant backlash within the developer community. Many feel blindsided by the sudden switch, describing it as a "bait and switch" tactic due to the lack of prior communication about the change.&lt;/p&gt;

&lt;p&gt;Developers have raised ethical concerns about monetizing a library that includes community contributions made under the previous Apache 2.0 license, emphasizing that contributors were unaware their work would later be used for profit. The pricing model—$129.95 per developer annually—has also been criticized as excessive for what many consider a utility library providing syntactic convenience rather than indispensable functionality.&lt;/p&gt;

&lt;p&gt;This controversy has led to broader discussions about trust in open-source projects, with some fearing that such moves could erode confidence in open-source software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implications for Developers and Organizations
&lt;/h2&gt;

&lt;p&gt;The new licensing model introduces financial and operational challenges for developers and organizations. Commercial users now face increased costs, especially for larger teams, with no transferable licenses allowed between developers. This adds friction to adopting or continuing to use Fluent Assertions in commercial settings.&lt;/p&gt;

&lt;p&gt;Furthermore, organizations may need to involve legal teams to review the new licensing terms, creating additional overhead. The sudden nature of this change forces teams to reassess their dependencies on Fluent Assertions, potentially delaying projects or requiring migration efforts. For many, this situation underscores the risks of relying heavily on third-party libraries without clear long-term sustainability plans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternatives and Recommendations
&lt;/h2&gt;

&lt;p&gt;In light of these changes, developers have several options moving forward. The simplest short-term solution is to lock dependencies to Fluent Assertions version 7, which remains under the Apache 2.0 license and allows free commercial use; for those seeking alternatives, libraries like &lt;a href="https://docs.shouldly.org/" rel="noopener noreferrer"&gt;Shouldly&lt;/a&gt; offer similar functionality with a fluent interface, while testing frameworks like &lt;a href="https://xunit.net/" rel="noopener noreferrer"&gt;xUnit&lt;/a&gt;, &lt;a href="https://nunit.org/" rel="noopener noreferrer"&gt;NUnit&lt;/a&gt;, and MSTest provide built-in assertion APIs that can serve as replacements.&lt;/p&gt;

&lt;p&gt;Teams may also consider implementing custom assertion methods tailored to their specific needs if their reliance on Fluent Assertions is limited. In the long term, organizations should evaluate whether fluent assertions are essential to their workflows and explore strategies to reduce dependency on third-party tools whenever possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Broader Open Source Concerns
&lt;/h2&gt;

&lt;p&gt;This situation highlights ongoing challenges in the open-source ecosystem, particularly around sustainability and monetization. While open source has brought immense value to software development, maintaining large projects often becomes an unpaid burden for contributors.&lt;/p&gt;

&lt;p&gt;These shifts raise questions about how open-source projects can balance accessibility with financial viability without alienating their user base. Moreover, frequent licensing changes risk eroding trust in open-source software, prompting companies to scrutinize dependencies more closely before adopting them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping it all up
&lt;/h2&gt;

&lt;p&gt;The licensing change for Fluent Assertions 8 marks a significant turning point for one of .NET's most popular testing libraries. It serves as a cautionary tale for developers relying on open-source tools. While this move addresses sustainability challenges, it has also sparked widespread criticism and uncertainty within the community. Developers must now weigh their options carefully—whether sticking with version 7, migrating to alternatives like Shouldly, or reevaluating their reliance on fluent assertions altogether.&lt;/p&gt;

&lt;p&gt;This incident underscores the importance of staying informed about the dependencies we rely on and fostering discussions about sustainable open-source models that benefit maintainers and users alike.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>testing</category>
      <category>opensource</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Building a Real-Time Santa's Workshop Tracker with SignalR and .NET 9</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Tue, 17 Dec 2024 05:00:09 +0000</pubDate>
      <link>https://forem.com/programazing/building-a-real-time-santas-workshop-tracker-with-signalr-and-net-9-37hd</link>
      <guid>https://forem.com/programazing/building-a-real-time-santas-workshop-tracker-with-signalr-and-net-9-37hd</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2l9zd63v09xruchnop4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2l9zd63v09xruchnop4.png" alt="Image description" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;This blog post is part of the 2024 &lt;a href="https://csadvent.christmas/" rel="noopener noreferrer"&gt;C# Advent Calendar&lt;/a&gt;. Go check out the other 49 great posts after you read mine, of course.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🎄🎅 &lt;strong&gt;Ho Ho Ho! Welcome to Santa's Coding Workshop!&lt;/strong&gt; 🧝💻&lt;/p&gt;

&lt;p&gt;'Tis the season to be jolly... and to code! Grab your candy cane stylus and put on your coding mittens because you're about to embark on a magical journey to the North Pole's most high-tech workshop!&lt;/p&gt;

&lt;p&gt;In this merry tutorial, you'll craft a real-time web application that brings Santa's workshop to life, powered by the enchanting duo of SignalR and .NET 9. Imagine a digital snow globe where you can peek inside and see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🧸 Elves busily crafting toys&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎁 Gift-wrapping stations buzzing with activity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🦌 Reindeer munching on magical carrots&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🍪 Ovens full of Mrs. Claus's famous cookies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📜 The Naughty-or-Nice list being checked twice&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All updating in real-time, faster than you can say "Jingle Bells"!Our festive application showcases modern web development practices, all wrapped up in a bow of Christmas cheer. Through a clean, simple interface that would make even Frosty the Snowman proud, users can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🧮 Watch the toy count climb towards Santa's goal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;👀 Spy on the activities of elves like Buddy, Jingle, Sparkle, Twinkle, and Holly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎅 Keep tabs on Santa's status&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the best part? No need to refresh the page - it's all as smooth as a sleigh ride!&lt;/p&gt;

&lt;p&gt;As you journey through the code, you'll see how to harness the power of WebSocket connections, sprinkled in some C# 13 magic dust, and leveraged SignalR's real-time capabilities to create an engaging and interactive workshop experience.&lt;/p&gt;

&lt;p&gt;So, hang your stockings by the chimney with care, and dive into the code to see how the magic happens! Remember, in Santa's workshop, every bug is just a feature in disguise, and every successful compile is like finding a present under the tree.&lt;/p&gt;

&lt;p&gt;Ready to code up some Christmas cheer? Jingle all the way to a winter wonderland of web development! 🎄&lt;/p&gt;

&lt;h2&gt;
  
  
  🎄 &lt;strong&gt;Getting the Workshop Ready!&lt;/strong&gt; 🎅🛠
&lt;/h2&gt;

&lt;p&gt;Kick off the festive coding adventure by setting up Santa's workshop project! First, you must create a shiny new ASP.NET Core Web Application using the magic of .NET 9. Grab your coding sleigh and run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new web &lt;span class="nt"&gt;-n&lt;/span&gt; SantasWorkshopTracker &lt;span class="nt"&gt;-f&lt;/span&gt; net9.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dash into the project directory, where all the holiday magic will unfold. Once you're there, its time to add the SignalR client library to bring the elves to life:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;SantasWorkshopTracker

dotnet add package Microsoft.AspNetCore.SignalR.Client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these steps, you're laying the foundation for a good time in Santas Workshop! Get ready to watch the magic unfold in an interactive experience thatll make even the North Pole proud! 🎁💻&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;🎄🔔&lt;/strong&gt; SantasWorkshopHub.cs: Santa's Communication Network &lt;strong&gt;🔔🎄&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Create a new file, &lt;code&gt;SantasWorkshopHub.cs&lt;/code&gt;, with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.SignalR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Diagnostics&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;SantasWorkshopTracker&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;ToyUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;SantaStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SantasWorkshopHub&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Hub&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ActivitySource&lt;/span&gt; &lt;span class="n"&gt;ActivitySource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SantasWorkshop.SignalR"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;



    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;_totalToys&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;UpdateToyProduction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ToyUpdate&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;

       &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ActivitySource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartActivity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

       &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ToyCount"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;



       &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;localTotal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_totalToys&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Simulating some async work&lt;/span&gt;

       &lt;span class="n"&gt;localTotal&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="n"&gt;_totalToys&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;localTotal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



       &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReceiveToyUpdate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ToyUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_totalToys&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;UpdateElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ElfActivity&lt;/span&gt; &lt;span class="n"&gt;elfActivity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;

       &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ActivitySource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartActivity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

       &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ElfName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elfActivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

       &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Activity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elfActivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReceiveElfUpdate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elfActivity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;UpdateSantaStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SantaStatus&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;

       &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ActivitySource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartActivity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

       &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReceiveSantaUpdate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;🌟 Unwrapping the Festive Features 🌟&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Record-Breaking Christmas Records&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;Our ToyUpdate, ElfActivity, and SantaStatus are wrapped up neatly as records. They're like perfectly packed presents, immutable and ready to spread joy!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Santa's Magic Telescope (ActivitySource)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ActivitySource&lt;/span&gt; &lt;span class="n"&gt;ActivitySource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SantasWorkshop.SignalR"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It isn't just any telescope; it's Santa's special way of watching all the workshop activities! 🔭&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tagging Toys and Elves&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;Each method uses ActivitySource to create activities and set tags. It's like Santa putting name tags on all the presents and elves!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ToyCount"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ElfName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elfActivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Async Christmas Magic&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;Our UpdateToyProduction method works asynchronously, just like elves working through the night to prepare all the toys!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SignalR's Christmas Broadcast&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;Clients.All.SendAsync is like Santa's magical announcement system, keeping everyone in the North Pole updated!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎊 Why This Code Sleighs 🎊&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Tracing&lt;/strong&gt; : With ActivitySource, you can track every toy made, every elf's activity, and Santa's status. It's like having a magical Christmas logbook! 📖&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-time Updates&lt;/strong&gt; : SignalR ensures everyone gets updates faster than Rudolph can fly! 🦌💨&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean and Concise&lt;/strong&gt; : Using records and modern C# features makes our code as neat as a wrapped gift!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This SantasWorkshopHub isn't just a piece of code; it's the heart of the virtual North Pole, pumping Christmas cheer and toy updates to all!🎄🎅🏻🧝&lt;/p&gt;

&lt;h2&gt;
  
  
  🧝 Elf Code Workshop: The Magical WorkshopSimulator 🧝
&lt;/h2&gt;

&lt;p&gt;Create a new file, &lt;code&gt;WorkshopSimulator.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.SignalR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;SantasWorkshopTracker&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WorkshopSimulator&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;_toyCount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ToyCount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WorkshopSimulator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IHubContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SantasWorkshopHub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hubContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BackgroundService&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt; &lt;span class="n"&gt;_random&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ToyGoal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Lock&lt;/span&gt; &lt;span class="n"&gt;_wrappingStationLock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;_availableWrappingStations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ToyCount&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_toyCount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;elfNames&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Buddy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Jingle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sparkle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Twinkle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Holly"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;elfActivities&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"making toys"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"feeding reindeer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"baking cookies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"checking the list"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsCancellationRequested&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;_toyCount&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ToyGoal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt; &lt;span class="c1"&gt;// Process 5 elves concurrently&lt;/span&gt;

            &lt;span class="p"&gt;{&lt;/span&gt;

                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;elfName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elfNames&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;

                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elfActivities&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfActivities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;

                &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ProcessElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WhenAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_toyCount&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;ToyGoal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;hubContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReceiveSantaStatus"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SantaStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ho Ho Ho! All toys are ready! Santa has departed! Merry Christmas!"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;ProcessElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;elfName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;activity&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"making toys"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;toysProduced&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;Interlocked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;_toyCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toysProduced&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;hubContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReceiveToyUpdate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ToyUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_toyCount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;WrapToy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;else&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;hubContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReceiveElfUpdate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;WrapToy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;elfName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wrapped&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;wrapped&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsCancellationRequested&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;lockScope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_wrappingStationLock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnterScope&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

            &lt;span class="p"&gt;{&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_availableWrappingStations&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="p"&gt;{&lt;/span&gt;

                    &lt;span class="n"&gt;_availableWrappingStations&lt;/span&gt;&lt;span class="p"&gt;--;&lt;/span&gt;

                    &lt;span class="n"&gt;wrapped&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wrapped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="p"&gt;{&lt;/span&gt;

                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;hubContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReceiveElfUpdate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"wrapping a gift"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Simulating wrapping time&lt;/span&gt;

                &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;lockScope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_wrappingStationLock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnterScope&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                &lt;span class="n"&gt;_availableWrappingStations&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;

            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;else&lt;/span&gt;

            &lt;span class="p"&gt;{&lt;/span&gt;

                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;hubContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ReceiveElfUpdate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"waiting for a wrapping station"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Wait before trying again&lt;/span&gt;

            &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;🎁 Unwrapping the Festive Features 🎁&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Magical Lock Spell&lt;/strong&gt; : The _wrappingStationLock is like Santa's magic key, ensuring orderly access to gift-wrapping stations!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Partial Properties - A Christmas Miracle&lt;/strong&gt; : Youve split the ToyCount property like sharing a Christmas cookie. Half the declaration, twice the joy!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collection Expressions - A Sack Full of Goodies&lt;/strong&gt; : The elf names and activities are now as neatly packed as Santa's gift bag, thanks to the new collection expression syntax!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concurrent Elf Magic&lt;/strong&gt; : Youre processing five elves at once, spreading holiday cheer faster than Rudolph on Christmas Eve!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Festive Randomness&lt;/strong&gt; : Just like you never know what's in a Christmas cracker, the _random adds a sprinkle of surprise to elf activities!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This code isn't just functional; it's a winter wonderland of C# 13 features! It's as exciting as finding the biggest present under the tree on Christmas morning! 🎄🎁&lt;/p&gt;

&lt;h2&gt;
  
  
  🎅🎄🏗 Program.cs: The North Pole's Command Center
&lt;/h2&gt;

&lt;p&gt;Update your &lt;code&gt;Program.cs&lt;/code&gt; file to add SignalR services and map the hub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;SantasWorkshopTracker&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSignalR&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHostedService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;WorkshopSimulator&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapHub&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SantasWorkshopHub&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"/santasworkshop"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseStaticFiles&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapFallbackToFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"index.html"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This jolly Program.cs sets up the North Pole operations center, connecting Santa's workshop to the digital world faster than you can say "Ho Ho Ho!" 🎅🏻🌟&lt;/p&gt;

&lt;h2&gt;
  
  
  🎄 Crafting Santa's Digital Dashboard 🖥
&lt;/h2&gt;

&lt;p&gt;Create a festive index.html in the &lt;code&gt;wwwroot&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Santa's Workshop Live Tracker&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f0f0f0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;800px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#c41e3a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nc"&gt;.update-section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Santa's Workshop Live Tracker&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"update-section"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Toy Production&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"toyCount"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toys made: 0&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"update-section"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Elf Activities&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"elfActivities"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"update-section"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Santa's Status&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"santaStatus"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Preparing for Christmas Eve&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"update-section"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Workshop Updates&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"workshopUpdates"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;signalR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HubConnectionBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/santasworkshop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configureLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signalR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Information&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ReceiveToyUpdate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toyCount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Toys made: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ReceiveElfUpdate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;li&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;elfActivities&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ReceiveSantaStatus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;santaStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;santaStatus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;santaStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;departed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;santaStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#c41e3a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;santaStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fontWeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bold&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ReceiveMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;li&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;workshopUpdates&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connected to Santa's Workshop!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connectionStatus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Connection error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connectionStatus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connection failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to connect to Santa's Workshop. Please try refreshing the page.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onclose&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Connection closed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unknown error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connectionStatus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Disconnected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connection to Santa's Workshop was lost. Please refresh the page to reconnect.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This magical interface brings Santa's workshop to life, updating faster than Rudolph's nose blinks! 🎅&lt;/p&gt;

&lt;h2&gt;
  
  
  🎅 Launching Santa's Workshop! 🎄
&lt;/h2&gt;

&lt;p&gt;Fire up the magic with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, dash over to &lt;a href="http://localhost:5000/" rel="noopener noreferrer"&gt;&lt;strong&gt;http://localhost:5000&lt;/strong&gt;&lt;/a&gt; in your browser to watch Santa's Workshop Live Tracker sparkle into action! 🎁&lt;/p&gt;

&lt;p&gt;You should see something that looks an awful lot like this!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsl6cev3xgfsvcdn6w8ev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsl6cev3xgfsvcdn6w8ev.png" width="800" height="899"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎁 Wrapping Up the Workshop
&lt;/h2&gt;

&lt;p&gt;🎄🎅 Ho ho ho! Time to unwrap the festive .NET 9 features for each class.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎅🎄🏗 Program.cs: The North Pole's Command Center&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🚀 Native AOT compilation: Faster than Rudolph on Christmas Eve!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎁 Improved performance: Santa's sleigh just got a turbo boost!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🔒 Enhanced security: Keeping those presents safe from the Grinch!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🧝 Elf Code Workshop: The Magical WorkshopSimulator 🧝&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;JIT enhancements: Elves are working faster than ever!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧮 Loop optimizations: Counting toys quicker than you can say "Ho Ho Ho!"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎨 PGO improvements: Painting toys with precision!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🔔 SantasWorkshopHub.cs: Santa's Communication Network&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;📡 Improved tracing: Tracking elves better than Santa's naughty-or-nice list!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🚀 Native AOT compatibility: Messages flying faster than reindeer!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧩 Polymorphic hub method arguments: Handling different types of Christmas wishes!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🎁 General .NET 9 Goodies:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🧠 AI building blocks: Helping elves make smarter toys!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📊 New Tensor types: Wrapping presents in multi-dimensional joy!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🔑 Improved cryptography: Keeping Santa's magic safe and sound!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📦 Enhanced ASP.NET Core: Delivering web presents smoother than ever!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These magical .NET 9 features will make this the most productive Christmas season yet for developers worldwide! 🌟🎄&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 &lt;strong&gt;Troubleshooting&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here are some common issues developers might encounter and how to resolve them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;SignalR Connection IssuesProblem&lt;/strong&gt; : SignalR fails to establish a connection.
&lt;strong&gt;Solution&lt;/strong&gt; : Ensure your firewall isn't blocking WebSocket connections. Check the console for any CORS-related errors and update your CORS policy if necessary.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; // In Program.cs
 builder.Services.AddCors(options =&amp;gt;
 {
     options.AddPolicy("CorsPolicy", builder =&amp;gt; builder
         .WithOrigins("http://localhost:5000")
         .AllowAnyMethod()
         .AllowAnyHeader()
         .AllowCredentials());
 });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Performance Bottlenecks in Toy ProductionProblem&lt;/strong&gt; : Toy production simulation runs slowly.
&lt;strong&gt;Solution&lt;/strong&gt; : Utilize parallel processing for elf activities and consider using &lt;code&gt;System.Threading.Channels&lt;/code&gt; for efficient producer-consumer scenarios.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt; &lt;span class="c1"&gt;// In WorkshopSimulator.cs&lt;/span&gt;
 &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_elfActivityChannel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateUnbounded&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

 &lt;span class="c1"&gt;// Producer&lt;/span&gt;
 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_elfActivityChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

 &lt;span class="c1"&gt;// Consumer&lt;/span&gt;
 &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_elfActivityChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WaitToReadAsync&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_elfActivityChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;elfActivity&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;ProcessElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfActivity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Memory Leaks in Long-Running SimulationsProblem&lt;/strong&gt; : Application memory usage grows over time.
&lt;strong&gt;Solution&lt;/strong&gt; : Implement proper disposal of resources and use weak references for long-lived objects.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt; &lt;span class="c1"&gt;// In WorkshopSimulator.cs&lt;/span&gt;
 &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;WeakReference&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_recentActivities&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WeakReference&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;());&lt;/span&gt;

 &lt;span class="c1"&gt;// Usage&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_recentActivities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ElfActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elfName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Important Tip&lt;/em&gt;&lt;/strong&gt; *: Always monitor your application's performance using tools like dotnet-counters or Application Insights to catch and address issues early.*&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Warning&lt;/em&gt;&lt;/strong&gt; *: Be cautious when implementing parallel processing in SignalR hubs. Ensure thread-safety and consider using* &lt;code&gt;SemaphoreSlim&lt;/code&gt; for controlled concurrency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;]]&amp;gt;&lt;/p&gt;

</description>
      <category>signalr</category>
      <category>csharp</category>
      <category>dotnet</category>
      <category>christmas</category>
    </item>
    <item>
      <title>Building a Real-Time IoT Dashboard with HarperDB and Node.js</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Fri, 28 Jun 2024 10:36:03 +0000</pubDate>
      <link>https://forem.com/programazing/building-a-real-time-iot-dashboard-with-harperdb-and-nodejs-4jkp</link>
      <guid>https://forem.com/programazing/building-a-real-time-iot-dashboard-with-harperdb-and-nodejs-4jkp</guid>
      <description>&lt;p&gt;Welcome to an exciting journey into the world of real-time data with HarperDB and Node.js! Imagine having an IoT dashboard that updates in real-time, giving instant insights into your data. Sounds intriguing, right? That's precisely what you'll build in this tutorial.&lt;/p&gt;

&lt;p&gt;HarperDB is a powerful tool that combines a distributed database, cache, application, and streaming system into a single process. This unique combination allows for high performance and simplicity at scale, making it an excellent choice for real-time applications. In this project, you'll leverage HarperDB's capabilities to create a real-time IoT dashboard.&lt;/p&gt;

&lt;p&gt;By the end of this tutorial, you'll have a fully functional dashboard that can visualize data from IoT devices in real-time.&lt;/p&gt;

&lt;p&gt;You'll learn how to:&lt;/p&gt;

&lt;p&gt;Set up and configure HarperDB&lt;br&gt;
Simulate an IoT device sending data&lt;br&gt;
Build a Node.js server to handle real-time data&lt;br&gt;
Create a dynamic frontend to display data&lt;/p&gt;

&lt;p&gt;Whether you're a seasoned developer or just getting started, this tutorial is designed to be hands-on and straightforward. Each step will guide you through the process, ensuring you understand how everything fits together. Ready to dive in and start building? Let's get started!&lt;/p&gt;
&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;Start by setting up HarperDB and then create the necessary project structure. Follow these steps to get everything in place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Installing and Configuring HarperDB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, you'll need to install HarperDB. If you haven't already, head to the HarperDB website for the installation instructions tailored to your operating system.&lt;br&gt;
After installing HarperDB, you need to start the HarperDB server. Open your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;harperdb run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a message indicating that HarperDB is up and running. By default, HarperDB runs on port 9925. You can access the HarperDB Studio at &lt;a href="http://localhost:9925" rel="noopener noreferrer"&gt;http://localhost:9925&lt;/a&gt; to manage your database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1719569968577%2F6aacb9d6-3fb0-4f27-9622-6b61ed214eca.png%3Fauto%3Dcompress%2Cformat%26format%3Dwebp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1719569968577%2F6aacb9d6-3fb0-4f27-9622-6b61ed214eca.png%3Fauto%3Dcompress%2Cformat%26format%3Dwebp" alt="Terminal output of starting HarperDB"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Setting Up the Project Directory and Necessary Files&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, set up the project directory. Open your terminal and navigate to your preferred workspace. Create a new directory for our project and navigate into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;real-time-iot-dashboard
&lt;span class="nb"&gt;cd &lt;/span&gt;real-time-iot-dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, initialize a new Node.js project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a package.json file with the default settings. Now, install the required dependencies. You’ll need Express for our server, Axios for making HTTP requests, and WebSocket for real-time communication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;express axios ws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the dependencies installed, you'll need to create the necessary files and directories. Run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;public
&lt;span class="nb"&gt;touch &lt;/span&gt;server.js public/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s a quick overview of what each file will do:&lt;br&gt;
server.js: This will be the main server file, handling HTTP and WebSocket connections.&lt;br&gt;
public/index.html: This will be the frontend file, displaying the real-time data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Configuring HarperDB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before moving on, you must set up a table in HarperDB to store the IoT data.&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;schema.graphql&lt;/code&gt; in your project directory, then paste the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;SensorData&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;id:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@primaryKey&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;timestamp:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;temperature:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;humidity:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a separate terminal window, run the following command to have HarperDB monitor the application directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;harperdb dev &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can learn more about creating tables in the Applications section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simulating an IoT Device
&lt;/h2&gt;

&lt;p&gt;With the project setup complete, it's time to simulate an IoT device sending data to HarperDB. Create a Node.js script that generates random sensor data and sends it to the HarperDB instance. Follow these steps to get started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Creating the Node.js Script&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, create a new file in the project directory called simulate_device.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;simulate_device.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open this file in your preferred code editor and start by requiring the necessary modules. Use Axios to send HTTP requests to HarperDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;uuidv4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The uuid library will generate unique IDs for the sensor data. Install this library by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;uuid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Generating Random Sensor Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, create a function to generate random sensor data. Assume the IoT device measures temperature and humidity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateSensorData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuidv4&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// Random temperature between 0 and 40&lt;/span&gt;
        &lt;span class="na"&gt;humidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Random humidity between 0 and 100&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Sending Data to HarperDB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, create a function to send the generated sensor data to HarperDB using the REST API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendDataToHarperDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:9926/SensorData&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Data sent successfully:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error sending data:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Automating Data Generation and Sending&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, create a loop to generate and send data at regular intervals. For instance, send data every 5 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateSensorData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;sendDataToHarperDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete &lt;code&gt;simulate_device.js&lt;/code&gt; script should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;uuidv4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateSensorData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuidv4&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;humidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendDataToHarperDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:9926/SensorData&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Data sent successfully:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error sending data:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateSensorData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;sendDataToHarperDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the script using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node simulate_device.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script will start generating random sensor data and sending it to HarperDB every 5 seconds. This setup simulates an IoT device and provides data for the real-time dashboard.&lt;br&gt;
In the next section, you'll build the real-time data ingestion setup, ensuring the IoT data flows smoothly into the dashboard.&lt;/p&gt;
&lt;h2&gt;
  
  
  Real-Time Data Ingestion
&lt;/h2&gt;

&lt;p&gt;Now that your IoT device simulation sends data to HarperDB, it's time to set up real-time data ingestion. This setup will allow the frontend to receive and display data as soon as it's available. Follow these steps to create a seamless flow of data from HarperDB to the dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Setting Up the Node.js Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, you'll create a Node.js server to handle real-time data communication. This server will use WebSocket to push updates to the frontend.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;server.js&lt;/code&gt; file and start by requiring the necessary modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ws&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, set up the basic Express server and HTTP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Serve static files from the 'public' directory&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Serve index.html at the root endpoint&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/public/index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Start the server on port 3000&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Server is running on http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Handling WebSocket Connections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set up the WebSocket server to handle connections and send real-time data to connected clients:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Client connected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Client disconnected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Fetching Data from HarperDB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To fetch data from HarperDB, create a function that retrieves the latest sensor data. Use this function to periodically check HarperDB for new data and send updates to the frontend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchDataAndUpdateClients&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:9925&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// HarperDB endpoint&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT * FROM data.SensorData ORDER BY timestamp DESC LIMIT 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;latestData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Check if the response data is an array (expected format)&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;latestData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Broadcast latest data to all connected clients&lt;/span&gt;
            &lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;latestData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unexpected data format:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;latestData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error fetching data:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Periodically fetch data and update clients every 5 seconds&lt;/span&gt;
&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchDataAndUpdateClients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function queries HarperDB for the latest sensor data and sends it to all connected WebSocket clients every 5 seconds.&lt;/p&gt;

&lt;p&gt;If you go to &lt;a href="http://localhost:9925/SensorData" rel="noopener noreferrer"&gt;http://localhost:9925/SensorData&lt;/a&gt; you should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1719570227418%2Fa52a4d65-3a33-459a-8696-a09e348eff87.png%3Fauto%3Dcompress%2Cformat%26format%3Dwebp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1719570227418%2Fa52a4d65-3a33-459a-8696-a09e348eff87.png%3Fauto%3Dcompress%2Cformat%26format%3Dwebp" alt="Output of the basic dashboard showing the id, timestamp, temperature, and humitity"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Setting Up the Frontend to Receive Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, configure the frontend to connect to the WebSocket server and display the received data. Open the &lt;code&gt;public/index.html&lt;/code&gt; file and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Real-Time IoT Dashboard&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Real-Time IoT Dashboard&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"dataContainer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Waiting for data...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dataContainer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ws://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;dataContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Clear previous data&lt;/span&gt;
                &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sensorData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;humidity&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sensorData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
                        &amp;lt;p&amp;gt;ID: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
                        &amp;lt;p&amp;gt;Timestamp: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
                        &amp;lt;p&amp;gt;Temperature: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; °C&amp;lt;/p&amp;gt;
                        &amp;lt;p&amp;gt;Humidity: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;humidity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; %&amp;lt;/p&amp;gt;
                        &amp;lt;hr&amp;gt;
                    `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nx"&gt;dataContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Received unexpected data format:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="c1"&gt;// Handle single data object case, if needed&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
                    &amp;lt;p&amp;gt;ID: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
                    &amp;lt;p&amp;gt;Unexpected data format, check console for details.&amp;lt;/p&amp;gt;
                `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nx"&gt;dataContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onopen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WebSocket connection established.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WebSocket connection closed.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code establishes a WebSocket connection to the server and updates the page with the latest sensor data.&lt;/p&gt;

&lt;p&gt;At this point the application should look like this:&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Dashboard
&lt;/h2&gt;

&lt;p&gt;Now that you've set up real-time data ingestion, it's time to build a polished and interactive dashboard to visualize the IoT data. Follow these steps to enhance the user interface and create dynamic charts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Setting Up Chart.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To create beautiful charts, use Chart.js. First, add the Chart.js library to your project. Include the following script tag in the &lt;/p&gt; section of your &lt;code&gt;public/index.html&lt;/code&gt; file:&lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/chart.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;2. Creating the HTML Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modify the HTML structure to include a canvas element for the chart. Update the &lt;code&gt;public/index.html&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Real-Time IoT Dashboard&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/chart.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"styles.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Chart.js loaded:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Check if Chart.js is loaded&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Real-Time IoT Dashboard&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"dataContainer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Waiting for data...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;canvas&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"myChart"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dataContainer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myChart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ws://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;dataContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Clear previous data&lt;/span&gt;
                &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sensorData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;humidity&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sensorData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
                        &amp;lt;p&amp;gt;ID: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
                        &amp;lt;p&amp;gt;Timestamp: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
                        &amp;lt;p&amp;gt;Temperature: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; °C&amp;lt;/p&amp;gt;
                        &amp;lt;p&amp;gt;Humidity: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;humidity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; %&amp;lt;/p&amp;gt;
                        &amp;lt;hr&amp;gt;
                    `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nx"&gt;dataContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nf"&gt;updateChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sensorData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Received unexpected data format:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="c1"&gt;// Handle single data object case, if needed&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
                    &amp;lt;p&amp;gt;ID: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
                    &amp;lt;p&amp;gt;Unexpected data format, check console for details.&amp;lt;/p&amp;gt;
                `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nx"&gt;dataContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataDiv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onopen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WebSocket connection established.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WebSocket connection closed.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;chart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="na"&gt;datasets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Temperature (°C)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                            &lt;span class="na"&gt;borderColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgba(255, 99, 132, 1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;borderWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
                        &lt;span class="p"&gt;},&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Humidity (%)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;humidity&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                            &lt;span class="na"&gt;borderColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgba(54, 162, 235, 1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;borderWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;scales&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;time&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;minute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                            &lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="p"&gt;},&lt;/span&gt;
                        &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;beginAtZero&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Destroy the existing chart instance&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nf"&gt;createChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Initializing the Chart&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createChart&lt;/code&gt; function initializes the chart with the first data point received. It sets up two datasets, one for temperature and one for humidity. The &lt;code&gt;updateChart&lt;/code&gt; function updates the chart with new data points as they arrive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Updating the Chart&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each time new data is received through the WebSocket, the &lt;code&gt;updateChart&lt;/code&gt; function adds the latest data to the chart and updates the display.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Styling the Dashboard&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add some basic CSS to improve the dashboard's appearance. Create a &lt;code&gt;public/styles.css&lt;/code&gt; file and include it in the HTML file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;#data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;canvas&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure your dashboard is optimized for mobile devices by implementing responsive design principles. Adjust layout and styling to provide a seamless user experience across different screen sizes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Example CSS for responsive design */&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;/* Adjust other styles as needed */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at this thing of beauty!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1719570257170%2F8ab54698-5c3c-47d2-ae58-322f02bcc424.png%3Fauto%3Dcompress%2Cformat%26format%3Dwebp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1719570257170%2F8ab54698-5c3c-47d2-ae58-322f02bcc424.png%3Fauto%3Dcompress%2Cformat%26format%3Dwebp" alt="The finished dashboard showing a graph of the temperature and humidity"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your interactive dashboard is now complete! It receives real-time data from the simulated IoT device and visualizes it using Chart.js. The dynamic chart updates automatically as new data arrives, providing a clear and engaging way to monitor sensor readings.&lt;/p&gt;

&lt;p&gt;Consider adding data analysis and insights features, such as trend analysis, statistical summaries, or predictive analytics based on historical data trends. These enhancements can provide valuable insights for users.&lt;/p&gt;

&lt;p&gt;By enhancing data visualization on the frontend, you're creating a more engaging and informative IoT dashboard. Experiment with these customization options to tailor the dashboard to your project's requirements and improve user interaction with real-time sensor data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping it up!
&lt;/h2&gt;

&lt;p&gt;Congratulations on building your own real-time IoT dashboard using HarperDB and Chart.js! Throughout this tutorial, we've covered essential steps to set up a robust data pipeline, visualize sensor data dynamically, and enhance user interaction with real-time alerts and responsive design.&lt;/p&gt;

&lt;p&gt;By customizing Chart.js configurations and integrating additional widgets, you've learned how to tailor data visualization to specific project needs. Implementing real-time alerts and notifications ensures timely updates on critical sensor readings, enhancing the dashboard's utility.&lt;br&gt;
Remember, optimizing for mobile and responsive design ensures a seamless user experience across devices, making your dashboard accessible anytime, anywhere. Exploring further enhancements like data analysis and insights can provide deeper insights into sensor trends and performance metrics.&lt;/p&gt;

&lt;p&gt;As you refine and expand your IoT dashboard, don't hesitate to experiment with different visualizations and features. Embrace a hands-on approach, iterate based on user feedback, and stay curious about new technologies and possibilities.&lt;/p&gt;

&lt;p&gt;Keep building, learning, and pushing the boundaries of what's possible with IoT and data visualization. Share your creations with the developer community and showcase your skills in crafting meaningful and impactful technical solutions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here are some other resources you might enjoy!&lt;/p&gt;

&lt;p&gt;How to Build a Real-Time Crypto Dashboard with HarperDB&lt;br&gt;
In this tutorial, Michael King demonstrates creating a straightforward dynamic dashboard to display cryptocurrency prices and news articles using HarperDB. The article covers setting up the database, using Angular for the frontend, and integrating RSS feed parsing.&lt;/p&gt;

&lt;p&gt;Real-Time Communication with HarperDB&lt;br&gt;
Learn about using WebSocket servers and HarperDB's leaf stream for real-time communication. This article explores setting up custom functions and creating a real-time chat application.&lt;/p&gt;

&lt;p&gt;Build a Dynamic REST API with Custom Functions&lt;br&gt;
Terra Roush's tutorial guides you through building a REST API with custom functions in HarperDB. It covers creating endpoints, handling requests, and integrating with your application.&lt;/p&gt;

</description>
      <category>iot</category>
      <category>dashboard</category>
      <category>charts</category>
      <category>node</category>
    </item>
    <item>
      <title>Navigating the World of Distractions</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Fri, 01 Sep 2023 12:00:12 +0000</pubDate>
      <link>https://forem.com/programazing/navigating-the-world-of-distractions-3a0</link>
      <guid>https://forem.com/programazing/navigating-the-world-of-distractions-3a0</guid>
      <description>&lt;ul&gt;
&lt;li&gt;The Challenge of Distractions: Understanding the Modern-Day Hurdles&lt;/li&gt;
&lt;li&gt;Common Distractions: Identifying the Culprits in Your Day&lt;/li&gt;
&lt;li&gt;Tools to Combat Distractions: Your Arsenal for a Focused Day&lt;/li&gt;
&lt;li&gt;Techniques and Strategies: Mastering the Art of Focus&lt;/li&gt;
&lt;li&gt;Special Considerations for ADHD: Navigating Distractions with an Extra Layer of Challenge&lt;/li&gt;
&lt;li&gt;Closing the Brackets: Embracing the Journey to a Distraction-Free You&lt;/li&gt;
&lt;li&gt;Additional Resources: Expanding Your Toolkit for Distraction Management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Welcome to the digital age, where the world is at your fingertips, and so are a million distractions. If you've ever found yourself diving deep into a YouTube rabbit hole when you were supposed to be working, or if your phone's ping lures you away from tasks more often than you'd like to admit, you're not alone. The freedom and flexibility of our connected world come with its challenges. And for those of you who, like me, have ADHD, the struggle to stay on track can feel even more pronounced.&lt;/p&gt;

&lt;p&gt;You might wonder, "Why is managing distractions so crucial?" Every time you're pulled away from a task, you lose not just those few minutes. Your brain takes additional time to refocus, making those brief moments of distraction add to significant chunks of unproductive time. And it's not just about lost time; it's about the mental fatigue, the frustration, and the feeling that you're always playing catch-up.&lt;/p&gt;

&lt;p&gt;But here's the good news: You have the power to change. With the right tools, techniques, and mindset, you can confidently navigate this world of constant notifications, pings, and pop-ups. You can reclaim your focus, boost your productivity, and find a balance that works for you.&lt;/p&gt;

&lt;p&gt;In this blog post, we'll dive deep into understanding these distractions, exploring tools that can help, and sharing strategies that have worked for many, including myself. So, if you're ready to take back control and make those distractions a thing of the past, read on. Your journey to a more focused and productive you starts here.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Challenge of Distractions: Understanding the Modern-Day Hurdles
&lt;/h1&gt;

&lt;p&gt;Have you ever felt like you're in a constant battle with distractions? You're trying to finish a report, but that tempting social media tab is waiting to be clicked. Or you're deep into a project, and suddenly, a notification pops up, pulling you into an entirely different world. It's a scenario all too familiar in our hyper-connected age.&lt;/p&gt;

&lt;p&gt;Let's face it: Distractions are everywhere. From the buzz of your phone to the allure of trending videos, the modern world is designed to capture your attention. And while technology has brought countless benefits, it's also introduced many ways to divert our focus.&lt;/p&gt;

&lt;p&gt;So, why do these distractions matter so much? For starters, they chip away at your most valuable resource: time. Every moment you spend scrolling through a feed or watching a video is time you can't get back. But it goes deeper than that. Distractions disrupt your flow, that magical state where work feels effortless and you're most productive. Each interruption forces your brain to switch gears, and returning to the zone takes longer than you might think.&lt;/p&gt;

&lt;p&gt;Moreover, there's a mental toll. Continually jumping between tasks can leave you feeling drained, even if you haven't accomplished much. It's like running on a treadmill; you move a lot but not get anywhere. And for those with ADHD, these challenges can be amplified, making it even harder to stay on track.&lt;/p&gt;

&lt;p&gt;But here's a thought: What if you could turn the tables on these distractions? Instead of being at their mercy, what if you could harness your environment, tools, and habits to work for you? The key lies in understanding the nature of these distractions and then crafting a strategy to minimize their impact.&lt;/p&gt;

&lt;p&gt;In the following sections, we'll delve into the most common culprits that pull you away from your tasks and offer actionable tips to help you stay on course. Whether it's silencing pesky notifications, using apps to block distracting sites, or simply changing your environment, there are ways to make distractions less... well, distracting.&lt;/p&gt;

&lt;p&gt;Remember, it's not about eliminating every single distraction. That's neither feasible nor desirable. After all, sometimes, a short break or a quick scroll can be refreshing. It's about finding a balance and understanding when to indulge and when to buckle down.&lt;/p&gt;

&lt;p&gt;So, as you continue reading, think about the distractions that resonate most with you. Recognizing them is the first step to managing them. And with the insights and tools we share, you'll be well on your way to a more focused, productive, and satisfying workday.&lt;/p&gt;

&lt;h1&gt;
  
  
  Common Distractions: Identifying the Culprits in Your Day
&lt;/h1&gt;

&lt;p&gt;Let's play a little game. Think back to your last workday and try to recall what pulled you away from your tasks. Was it a sudden urge to check Instagram? Perhaps a chatty colleague? Or it was the allure of a new email notification. Whatever it was, recognizing these distractions was the first step to taming them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Social Media's Siren Call:&lt;/strong&gt; Ah, social media. Platforms like Facebook, Twitter, and Instagram are designed to keep you scrolling. With their endless feeds and constant updates, losing track of time is easy. And while staying connected is essential, especially in today's world, setting boundaries is crucial. Allocate specific times in your day for social media checks, and stick to them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Email Avalanche:&lt;/strong&gt; You're deep in work, and a new email notification suddenly appears. It's tempting to check. But you're breaking your workflow whenever you divert your attention to an email. Consider setting specific times for checking emails, like once in the morning and once in the afternoon. And for those super urgent matters? Trust that people will find other ways to reach you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Chatterbox Colleague:&lt;/strong&gt; We all have that one colleague who loves to chat. While workplace camaraderie is essential, constant interruptions can hamper productivity. Politely set boundaries or consider using headphones as a universal "do not disturb" sign.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Smartphone Buzz:&lt;/strong&gt; From WhatsApp messages to news alerts, our phones are constantly distracting. Ask yourself, do you need to be available 24/7? Most times, the answer is no. Consider using features like "Do Not Disturb" during work hours or placing your phone face down to avoid the lure of flashing notifications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Background Noise Trap:&lt;/strong&gt; While some people thrive with background noise, for others, it can be a significant distraction. If you're the latter, consider noise-canceling headphones or apps that play white noise to drown out distractions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Personal Tasks and Errands:&lt;/strong&gt; Remembering to book a doctor's appointment or order groceries can pull you away from work. Keep a separate to-do list for individual tasks and allocate specific breaks to tackle them.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For those with ADHD, these distractions can feel magnified. The key is to tailor your strategies to what works best for you. It could be a combination of tools, environmental changes, or simply setting clear boundaries.&lt;/p&gt;

&lt;p&gt;As you navigate your workday, be kind to yourself. Distractions happen to the best of us. It's not about achieving perfection but progress. By identifying these common culprits and implementing strategies to manage them, you're already on the path to a more focused and productive day. And remember, every step you take towards working these distractions is a step closer to achieving your goals. So, gear up, and let's tackle these distractions head-on!&lt;/p&gt;

&lt;h1&gt;
  
  
  Tools to Combat Distractions: Your Arsenal for a Focused Day
&lt;/h1&gt;

&lt;p&gt;Now that you've identified those pesky distractions, it's time to arm yourself with tools to help you fend them off. Think of these tools as your guardians, standing between you and the myriad of distractions vying for your attention.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://getcoldturkey.com/"&gt;&lt;strong&gt;Cold Turkey&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;:&lt;/strong&gt; Ever wished you could temporarily block out distracting websites? Enter Cold Turkey. It's like a digital bouncer for your computer. Whether you're tempted to check out the latest memes or fall into a Wikipedia spiral, Cold Turkey can block those sites during your designated work hours. And the best part? It's available across multiple platforms, ensuring distractions, no matter your device, can't sneak in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://appblock.app/"&gt;&lt;strong&gt;AppBlock&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;:&lt;/strong&gt; Your phone can be both a tool and a temptation. AppBlock steps in to keep those distracting apps at bay. Set it up to block access to apps like Instagram, Twitter, or any game that pulls you in during work hours. It's like having a personal assistant gently reminding you to stay on task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.focusatwill.com/"&gt;&lt;strong&gt;Focus@Will&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;:&lt;/strong&gt; If silence isn't your thing and regular music distracts you, give Focus@Will a try. It offers specially curated tracks designed to boost concentration and productivity. It's not just music; science-backed audio enhances your focus.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.rescuetime.com/"&gt;&lt;strong&gt;RescueTime&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;:&lt;/strong&gt; Ever wondered where your day went? RescueTime gives you a clear picture. It tracks your time on apps and websites, giving you a detailed report of your digital day. Understanding where your time goes allows you to make informed decisions and tweak your routine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.forestapp.cc/"&gt;&lt;strong&gt;Forest&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;:&lt;/strong&gt; Turn focus into a game! With Forest, you plant a virtual tree whenever you want to concentrate. If you stay on task, your tree grows. Get distracted, and it withers. It's a fun way to track and reward your focus visually.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While these tools are fantastic, remember they're just one piece of the puzzle. They work best when combined with the techniques and strategies we'll delve into in the following sections. But for now, take a moment to explore these tools and see which ones resonate with you.&lt;/p&gt;

&lt;p&gt;And a quick note for my fellow ADHD warriors: tools can be especially beneficial for us, offering that extra layer of support. So, don't hesitate to experiment and find what combination works best for you.&lt;/p&gt;

&lt;p&gt;Ultimately, it's all about creating an environment where you can thrive. With these tools in your arsenal, you're not just combating distractions but setting yourself up for success. So, gear up, dive in, and make every workday a productivity masterpiece!&lt;/p&gt;

&lt;h1&gt;
  
  
  Techniques and Strategies: Mastering the Art of Focus
&lt;/h1&gt;

&lt;p&gt;Beyond the digital tools, a world of techniques and strategies can elevate your focus game. Think of these as the habits and routines that, when practiced consistently, can transform how you work and live. Ready to dive in? Let's explore.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Time-Blocking:&lt;/strong&gt; Imagine your day as a series of blocks dedicated to a specific task or activity. You create a roadmap for your day by allocating set times for tasks. It's not just about work; block out time for breaks, meals, and even those social media checks. Giving everything its own time reduces the urge to multitask, often leading to multi-distracting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Pomodoro Technique:&lt;/strong&gt; Named after the Italian word for tomato (thanks to its tomato-shaped timer), this technique involves working intensely for 25 minutes and then taking a 5-minute break. Repeat this cycle, and you'll find that these short bursts of focus can lead to monumental productivity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Declutter Your Workspace:&lt;/strong&gt; A cluttered desk can lead to a cluttered mind. Organize your workspace for a few minutes at the start or end of each day. A clean, organized space can do wonders for your mental clarity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mindfulness and Meditation:&lt;/strong&gt; Have you ever felt like your mind is racing with a million thoughts? Mindfulness practices can help you center yourself. Even a 5-minute meditation session can reset your mind, making tackling tasks with renewed focus easier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set Clear Goals:&lt;/strong&gt; Knowing what you need to achieve directs your day. Start with a clear list of tasks, prioritize them, and then tackle them individually. Celebrate small victories along the way; every checked-off item is a step closer to your goals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limit Multitasking:&lt;/strong&gt; While juggling multiple tasks might be productive, studies show it can reduce your efficiency. Instead, immerse yourself in one task at a time. Give it your full attention, complete it, and then move on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Regular Breaks:&lt;/strong&gt; All work and no play can drain your energy. Schedule short breaks to stretch, take a walk, or breathe. These moments of rest can recharge you, making it easier to dive back into work with vigor.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember, it's not about implementing all these strategies at once. It's about finding what resonates with you and integrating it into your routine. And as you experiment, you'll discover a blend of techniques that work uniquely for you.&lt;/p&gt;

&lt;p&gt;For those navigating ADHD, some of these strategies can be particularly impactful. For instance, the structure provided by time-blocking or the Pomodoro Technique can offer a clear framework to channel your energy.&lt;/p&gt;

&lt;p&gt;In the end, mastering focus is an ongoing journey. There will be days of incredible productivity and days where distractions win. And that's okay. The goal is progress, not perfection. With every technique you adopt and every distraction you overcome, you're crafting a work routine that's efficient, fulfilling, and uniquely yours. So, embrace the journey, celebrate the wins, and remember every focused moment is a triumph.&lt;/p&gt;

&lt;h1&gt;
  
  
  Special Considerations for ADHD: Navigating Distractions with an Extra Layer of Challenge
&lt;/h1&gt;

&lt;p&gt;For many of you reading this, distractions might be an occasional hurdle. But for those with ADHD, like myself, these distractions often feel like towering walls. The constant influx of stimuli and the unique way our brains process information can make focus seem elusive. But here's the silver lining: With the right strategies tailored to ADHD, you can manage and thrive amidst these challenges.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prioritize and Simplify:&lt;/strong&gt; With a whirlwind of thoughts often swirling in your mind, it's crucial to streamline. Start your day by listing tasks, then pick the top three most important ones. Focus on these first. By narrowing down your to-do list, you reduce the overwhelm and create a clear path for the day.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Visual Aids:&lt;/strong&gt; Visual cues can be a game-changer. Whether it's a physical planner, sticky notes on your desk, or digital tools with visual reminders, having something tangible to refer to can anchor your focus.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create ADHD-Friendly Workspaces:&lt;/strong&gt; Your environment plays a pivotal role. Consider creating zones in your workspace for different tasks. A quiet corner for deep work, a more open space for brainstorming, or even a comfy nook for breaks. These physical distinctions can cue your brain into the task at hand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Embrace Movement:&lt;/strong&gt; Sitting still can be a challenge. So, why fight it? If you think better on your feet, consider a standing desk. Or take short breaks to do a quick physical activity, be it a stretch or a walk around the block. Movement can help in channeling excess energy and refocusing your mind.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set Timers:&lt;/strong&gt; Use alarms and timers to segment your work. Knowing there's a set end time can make it easier to dive into a task. Plus, the alarm serves as a reminder if you do get sidetracked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seek Support:&lt;/strong&gt; Whether joining an ADHD support group, seeking therapy, or simply having an accountability partner, sharing your challenges and victories can make the journey less isolating. Remember, there's strength in community.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Celebrate the ADHD Strengths:&lt;/strong&gt; ADHD comes with its challenges but also brings a unique set of strengths. Embrace your creativity, ability to think outside the box, and boundless energy. By focusing on these positives, you can harness them to your advantage.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To my fellow ADHD warriors, I get it. The world often feels like it's set to a different rhythm. But with every strategy you adopt, you're managing distractions and creating a work environment that understands and celebrates your unique brain.&lt;/p&gt;

&lt;p&gt;And to everyone reading, whether you have ADHD or not, remember that the journey to focus is deeply personal. What works for one might not work for another. It's all about exploration, understanding, and patience. With every tool and technique, you're crafting a path that leads to a more productive, fulfilling, and balanced you. So, embrace the journey, and let's conquer those distractions together!&lt;/p&gt;

&lt;h1&gt;
  
  
  Closing the Brackets: Embracing the Journey to a Distraction-Free You
&lt;/h1&gt;

&lt;p&gt;As we wrap up this deep dive into managing distractions, I want you to take a moment and reflect. Think about the myriad of daily distractions and recognize that being pulled in different directions is a shared experience in today's digital age. But here's the empowering part: You have the tools, techniques, and insights to navigate this landscape confidently.&lt;/p&gt;

&lt;p&gt;Whether you're harnessing the power of apps like Cold Turkey and AppBlock, adopting time-tested techniques like the Pomodoro method, or embracing the unique strengths of ADHD, remember that every step you take is progress. It's about building habits, understanding your triggers, and crafting a work environment that resonates with who you are.&lt;/p&gt;

&lt;p&gt;But let's be honest for a moment. Will every day be a pinnacle of productivity? Probably not. And that's perfectly okay. Life is unpredictable, and there will be days when distractions win out. But instead of beating yourself up, use those moments as learning opportunities. Ask yourself, "What pulled me away?" and "How can I better prepare next time?" By approaching distractions with curiosity rather than frustration, you transform them from hurdles into stepping stones.&lt;/p&gt;

&lt;p&gt;And for those moments when you feel overwhelmed, remember you're not alone in this journey. Whether seeking support from fellow ADHD warriors, sharing your challenges with a trusted colleague, or simply revisiting this blog post for a refresher, there's a community and a wealth of resources at your fingertips.&lt;/p&gt;

&lt;p&gt;So, as you move forward, I urge you to celebrate the small victories. That report you finished without checking your phone? A win. The day you powered through without falling into a YouTube spiral? Another triumph. By focusing on these successes, you build momentum, making it easier to tackle more considerable challenges.&lt;/p&gt;

&lt;p&gt;Managing distractions isn't just about boosting productivity; it's about reclaiming your time, mental well-being, and the joy of immersing yourself in meaningful work. So, armed with insights and a renewed sense of purpose, go forth and conquer your day. Here's to a more focused, balanced, and empowered you!&lt;/p&gt;

&lt;h1&gt;
  
  
  Additional Resources: Expanding Your Toolkit for Distraction Management
&lt;/h1&gt;

&lt;p&gt;Diving into distraction management, you've already armed yourself with many strategies and tools. But the journey continues. The realm of productivity and focus is vast, and there's always more to explore. To further bolster your arsenal, I've curated a list of additional resources that can offer deeper insights, fresh perspectives, and innovative techniques.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Books to Elevate Your Focus Game:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.calnewport.com/books/deep-work/"&gt;&lt;em&gt;Deep Work&lt;/em&gt; by Cal Newport&lt;/a&gt;: Dive into the concept of deep, uninterrupted work and discover strategies to achieve this coveted state of flow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.the1thing.com/"&gt;&lt;em&gt;The One Thing&lt;/em&gt; by Gary Keller and Jay Papasan&lt;/a&gt;: Unearth the power of prioritizing that 'one thing' that can make everything else easier or unnecessary.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Podcasts for Productivity Enthusiasts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.asianefficiency.com/our-podcast/"&gt;&lt;em&gt;The Productivity Show&lt;/em&gt;&lt;/a&gt;: Tune in for productivity experts' actionable tips, techniques, and strategies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.beyondthetodolist.com/"&gt;&lt;em&gt;Beyond the To-Do List&lt;/em&gt;&lt;/a&gt;: Delve into personal productivity perspectives, offering insights into how various individuals conquer their tasks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Apps Beyond the Usual Suspects:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://Brain.fm"&gt;&lt;em&gt;Brain.fm&lt;/em&gt;&lt;/a&gt;: Experience music designed for the brain to enhance focus, relaxation, and even sleep.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://chrome.google.com/webstore/detail/stayfocusd/laankejkbhbdhmipfmgcngdelahlfoji?hl=en"&gt;&lt;em&gt;StayFocusd&lt;/em&gt;&lt;/a&gt;: A browser extension that restricts your time on time-wasting websites.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://francescocirillo.com/pages/pomodoro-technique"&gt;&lt;em&gt;Pomodoro Technique&lt;/em&gt;&lt;/a&gt;: A time management method that can help you break your work into intervals, separated by short breaks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.forestapp.cc/en/"&gt;&lt;em&gt;Forest App&lt;/em&gt;&lt;/a&gt;: An app that encourages you to stay focused by planting virtual trees that grow as you work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Online Courses to Sharpen Your Skills:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.udemy.com/course/become-highly-productive/"&gt;Productivity: Master 9+ Ways to Become Highly Productive&lt;/a&gt;: A comprehensive course that covers techniques from time management to brain science.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.linkedin.com/learning/time-management-fundamentals-14548057/the-power-of-managing-your-time"&gt;&lt;em&gt;Time Management Fundamentals&lt;/em&gt; on LinkedIn Learning&lt;/a&gt;: Equip yourself with foundational skills to manage your time effectively.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Forums and Communities:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.reddit.com/r/productivity/"&gt;&lt;em&gt;r/productivity&lt;/em&gt; on Reddit&lt;/a&gt;: Join a community of like-minded individuals, sharing tips, tricks, and stories of triumphs and challenges.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.focusmate.com/"&gt;&lt;em&gt;Focusmate&lt;/em&gt;&lt;/a&gt;: Connect with accountability partners for virtual co-working sessions, ensuring you stay on task.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you delve into these resources, remember to approach them open-mindedly. What works wonders for one person might not resonate with you, and that's perfectly fine. The goal is to gather diverse tools and strategies, experimenting until you find the perfect blend that aligns with your unique workflow and challenges.&lt;/p&gt;

&lt;p&gt;And if you stumble upon a gem not listed here, I'd love to hear about it! Sharing resources, experiences, and insights is how we grow individually and as a community. By pooling our knowledge, we can collectively navigate the maze of distractions and emerge on the other side more focused and empowered.&lt;/p&gt;

</description>
      <category>distractions</category>
      <category>life</category>
    </item>
    <item>
      <title>Terraform's License Change: A Deep Dive into the Controversy</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Thu, 31 Aug 2023 12:00:09 +0000</pubDate>
      <link>https://forem.com/programazing/terraforms-license-change-a-deep-dive-into-the-controversy-3m34</link>
      <guid>https://forem.com/programazing/terraforms-license-change-a-deep-dive-into-the-controversy-3m34</guid>
      <description>&lt;ul&gt;
&lt;li&gt;The License Change&lt;/li&gt;
&lt;li&gt;Why the Change?&lt;/li&gt;
&lt;li&gt;Community Backlash&lt;/li&gt;
&lt;li&gt;The Broader Implications&lt;/li&gt;
&lt;li&gt;Closing the Brackets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Navigating the world of open-source software can sometimes feel like walking through a maze. Just when you think you've got the lay of the land, a sudden turn can change everything. If you've been watching the tech landscape recently, you've probably heard about &lt;a href="https://www.hashicorp.com/blog"&gt;HashiCorp's decision&lt;/a&gt; regarding Terraform's licensing. Such a change isn't merely a topic for developers and tech enthusiasts; it has broader implications for businesses and the open-source community at large.&lt;/p&gt;

&lt;p&gt;If you're wondering why this matters to you, let me break it down. Terraform is an infrastructure-as-code tool for those who might be new to it. Many have found it a game-changer, allowing developers and IT professionals like you to manage and provision their tech stacks using code. The beauty of Terraform has always been its open-source nature, giving you the freedom to use, modify, and even redistribute the software. However, with HashiCorp's recent announcement, the rules of the game are changing.&lt;/p&gt;

&lt;p&gt;Imagine you've spent years mastering a tool, integrating it into your workflows, and then suddenly, the foundational principles of that tool shift. It's akin to mastering the art of chess, only to be told the pawns now move differently. Many in the community feel this kind of disruption. While change is an inherent part of the tech world, understanding the 'why' behind such decisions becomes crucial, especially when they impact tools you use daily.&lt;/p&gt;

&lt;p&gt;Before diving deeper into the specifics of the license change, its reasons, and the community's response, let's reflect on the broader landscape of open-source software. Open-source has always been about collaboration, a community coming together to build something more significant than the sum of its parts. It's about giving you the tools and the freedom to innovate, create, and push boundaries. Licensing, though it might seem like a small cog in this vast machinery, plays a pivotal role in determining how you interact with the software, how businesses monetize it, and how the community evolves, as highlighted by the &lt;a href="https://opentf.org/"&gt;OpenTF project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As we delve into the nitty-gritty of Terraform's licensing change in the following sections, please keep an open mind. Every story has multiple facets, and while jumping to conclusions is easy, understanding the nuances offers a clearer picture. Whether you're a developer, a business owner, or just someone curious about the latest tech world, our deep dive into Terraform's licensing controversy promises insights that shape how you view open-source in the future.&lt;/p&gt;

&lt;h1&gt;
  
  
  The License Change
&lt;/h1&gt;

&lt;p&gt;When you first started using Terraform, its most appealing features were undoubtedly its open-source nature. It's a sentiment many in the tech community share. The freedom to use, modify, and distribute software without restrictive barriers has always been the cornerstone of open-source projects. But, as with many things in life, change is inevitable.&lt;/p&gt;

&lt;p&gt;Recently, HashiCorp announced a pivotal shift in the licensing of Terraform, moving from its previous open-source license to the &lt;a href="https://www.hashicorp.com/bsl"&gt;Business Source License (BSL)&lt;/a&gt;. If you're unfamiliar with BSL, it's a license that allows for copying, modifying, and even redistributing the code. However, there's a catch. Commercial use, under BSL, comes with specific conditions. For Terraform, it means you can't offer a competitive service using their code. In simpler terms, while you can still use and modify Terraform, the new license restricts how you can commercially benefit from it.&lt;/p&gt;

&lt;p&gt;You might be wondering, "Why does it matter?" Well, for many businesses and individual developers, these licensing terms can significantly impact how they use the software. If you've built services or products around Terraform, the new licensing might require you to rethink your strategies or look for alternatives.&lt;/p&gt;

&lt;p&gt;But it's about more than just the immediate impact. Licensing changes, especially for popular tools like Terraform, set precedents. They influence how other companies approach open-source and can shape the future software development landscape. Will others follow suit if one major player shifts away from a purely open-source model? It's a question many are asking, and the answers could redefine how you interact with your favorite tools.&lt;/p&gt;

&lt;p&gt;Now, while it's easy to view such changes with skepticism, it's also essential to understand their motivations. The following section will delve deeper into why HashiCorp made this move. But for now, as you reflect on the license change, consider its broader implications. How will it affect your projects? Will it change your perception of Terraform? And most importantly, how will it influence your future decisions regarding the tools you choose to integrate into your tech stack?&lt;/p&gt;

&lt;h1&gt;
  
  
  Why the Change?
&lt;/h1&gt;

&lt;p&gt;Diving into the heart of the matter, you might ask yourself, "Why would HashiCorp, a company built on open-source principles, make such a significant shift in Terraform's licensing?" It's a valid question, and the answer lies at the intersection of business strategy, competition, and the evolving landscape of open-source software.&lt;/p&gt;

&lt;p&gt;Firstly, let's address the elephant in the room: competition. In the tech world, giants like Amazon and Google dominate the scene. They have the resources and reach to take an open-source tool, adapt it, and offer it as a paid service on their platforms. For companies like HashiCorp, this poses a significant challenge. Imagine spending years of effort developing a tool, only to see it repackaged and sold by a tech behemoth, cutting into your potential revenue streams. By switching to the Business Source License, HashiCorp aims to protect its products from such commercial repurposing. It's a move to ensure that while you, the user, continue to benefit from Terraform, HashiCorp remains the primary entity that can monetize it on a large scale.&lt;/p&gt;

&lt;p&gt;Then there's the financial perspective. If you've been tracking tech stocks or industry news, you might know that &lt;a href="https://www.globenewswire.com/news-release/2021/11/29/2342524/0/en/HashiCorp-Announces-Launch-of-Initial-Public-Offering.html"&gt;HashiCorp went public in 2021&lt;/a&gt;. For any public company, especially in the tech sector, there's immense pressure to show profitability and appease shareholders. By tightening the reins on how their products are used commercially, HashiCorp is safeguarding its revenue streams, aiming for a more stable financial future.&lt;/p&gt;

&lt;p&gt;Lastly, it's essential to understand that the open-source world isn't static. It's evolving, with new challenges and opportunities emerging regularly. As more companies adopt open-source models, the lines between pure open-source and commercial interests often blur. HashiCorp's decision reflects a broader trend where companies try to balance staying true to open-source principles and ensuring financial viability. It's a tightrope walk, and the choices can have ripple effects throughout the industry.&lt;/p&gt;

&lt;p&gt;While the licensing change might seem sudden or even alarming, it's rooted in a complex web of business decisions, competitive pressures, and the ever-changing dynamics of the open-source world. As you navigate these changes, staying informed is crucial, understanding the motivations behind such decisions and adapting your strategies accordingly. Remember, change is the only constant in the tech world, and staying ahead often means understanding the 'why' as much as the 'what'.&lt;/p&gt;

&lt;h1&gt;
  
  
  Community Backlash
&lt;/h1&gt;

&lt;p&gt;The community doesn't stay silent whenever there's a significant shift in the tech landscape, especially one that impacts beloved open-source tools. And why should you? After all, the collective voice of developers, IT professionals, and tech enthusiasts like you shape the future of software. So, the response was swift when &lt;a href="https://www.hashicorp.com/blog/hashicorp-adopts-business-source-license"&gt;HashiCorp announced Terraform's licensing change&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the most notable reactions came from the OpenTF project. A group of dedicated developers and Terraform enthusiasts banded together, voicing their concerns and urging HashiCorp to reconsider. When it became clear that a revert to the original license wasn't on the cards, they took matters into their own hands. The result? The official launch of the &lt;a href="https://github.com/opentffoundation/manifesto"&gt;OpenTF fork of HashiCorp Terraform&lt;/a&gt;. Their mission is simple yet powerful: to keep Terraform genuinely open-source. And they're not stopping there. Ambitions are high, with aspirations for OpenTF to join the ranks of the Linux Foundation and, eventually, the Cloud Native Computing Foundation.&lt;/p&gt;

&lt;p&gt;Amidst these strong reactions, some voices in the community took a more measured approach. While they acknowledged the restrictive nature of the new license, they also pointed out that it was a partial departure from open-source. HashiCorp's new license retains some open-source characteristics but with a twist - it's open-source with conditions, especially regarding commercial use.&lt;/p&gt;

&lt;p&gt;You might wonder, "What does all of this mean for me?" Whether you're a Terraform user, a business owner, or just an observer, these developments highlight a crucial aspect of the tech world: the power of community. Tools like Terraform aren't just lines of code; they're ecosystems built on collaboration, feedback, and shared goals. When those ecosystems face disruptions, it's up to you and the broader community to voice concerns, seek solutions, and shape the path forward.&lt;/p&gt;

&lt;p&gt;As we explore the broader implications of HashiCorp's decision, remember that your voice, perspective, and choices matter. The community remains at the heart of innovation in a world driven by technology.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Broader Implications
&lt;/h1&gt;

&lt;p&gt;In the ever-evolving world of technology, decisions made by one company can send ripples across the entire industry. HashiCorp's licensing shift with Terraform isn't just a standalone event; it reflects broader trends and challenges many open-source projects face today. As you navigate these waters, understanding these implications can help you make informed decisions, whether selecting tools for your next project or pondering the future of open-source.&lt;/p&gt;

&lt;p&gt;Firstly, let's talk about the essence of open-source. It's not just about free access to code; it's a philosophy, a commitment to collaboration, transparency, and community-driven innovation. When a prominent player like HashiCorp introduces restrictions, even if for valid business reasons, it prompts a crucial question: Where is the line between protecting business interests and preserving the spirit of open-source? As you evaluate tools and platforms for your projects, you might weigh these very considerations.&lt;/p&gt;

&lt;p&gt;Next, consider the competitive landscape. With tech giants capable of repurposing open-source tools for commercial gain, smaller companies often find themselves in a David vs. Goliath scenario. HashiCorp's move can be seen as a protective measure, a shield against potential commercial exploitation. But what does it mean for you? If more companies adopt similar licensing models, you might navigate a maze of terms and conditions, even for tools that were once purely open-source. It's a potential future where the tools you rely on come with strings attached.&lt;/p&gt;

&lt;p&gt;Then, there's the power of community-driven alternatives. The emergence of projects like OpenTF underscores the community's resilience and adaptability. If one door closes, another opens. For you, this means more choices but highlights the importance of staying informed and connected. Being part of tech communities, forums, and networks can ensure you're always in the loop, ready to adapt and pivot as the landscape changes.&lt;/p&gt;

&lt;p&gt;Lastly, think about innovation. Open-source has always been a hotbed for creativity, with diverse minds coming together to solve complex problems. Restrictive licenses deter some from contributing, potentially slowing the pace of innovation. For you, as a developer or tech enthusiast, it's worth pondering: Will the tools of tomorrow be as dynamic and groundbreaking if they're entangled in commercial restrictions?&lt;/p&gt;

&lt;p&gt;In conclusion, while HashiCorp's decision with Terraform is a focal point today, it's part of a larger narrative. The challenges of balancing business interests with open-source principles, the dynamics of competition, and the ever-present spirit of community innovation are themes that will continue to shape the tech world. As you move forward, armed with knowledge and insights, remember you're not just passive observers. You're a participant, a contributor, and a driving force in this ever-evolving story.&lt;/p&gt;

&lt;h1&gt;
  
  
  Closing the Brackets
&lt;/h1&gt;

&lt;p&gt;Navigating the intricate dance of technology, business, and community is challenging. As you've journeyed with me through the twists and turns of Terraform's licensing saga, it's evident that the open-source world is at a crossroads. But what does it all mean for you, and where do we go from here?&lt;/p&gt;

&lt;p&gt;HashiCorp's decision with Terraform is a testament to open-source pioneers' challenges in today's competitive landscape. Protecting business interests while staying true to the ethos of open collaboration is a delicate balance. For you, as a developer, business owner, or tech enthusiast, it underscores the importance of adaptability. The tools and platforms you've come to rely on today might evolve tomorrow, and staying agile is vital.&lt;/p&gt;

&lt;p&gt;The emergence of community-driven initiatives like OpenTF is a beacon of hope. It's a reminder that the tech community gets going when the going gets tough. Your voice, combined with those of thousands of others, can shape the trajectory of software development, ensuring that the spirit of open-source remains alive and well.&lt;/p&gt;

&lt;p&gt;The tech world is in constant flux, and change is its only constant. Embracing this change, understanding its nuances, and making informed decisions will be your compass in this ever-shifting landscape.&lt;/p&gt;

&lt;p&gt;As we wrap up our deep dive into Terraform's licensing controversy, stay curious, informed, and, most importantly, engaged. The future of open-source, in many ways, rests in your hands. Whether you're contributing to a project, voicing your opinions on forums, or making strategic decisions for your business, remember that you're an integral part of this narrative. Together, we can ensure that the open-source world continues to thrive, innovate, and inspire.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>hashicorp</category>
      <category>license</category>
    </item>
    <item>
      <title>Understanding Developer Burnout: Causes, Impact, and Solutions</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Wed, 30 Aug 2023 12:00:12 +0000</pubDate>
      <link>https://forem.com/programazing/understanding-developer-burnout-causes-impact-and-solutions-28km</link>
      <guid>https://forem.com/programazing/understanding-developer-burnout-causes-impact-and-solutions-28km</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Why Developers Burn Out:&lt;/li&gt;
&lt;li&gt;Burnout in the Age of COVID-19:&lt;/li&gt;
&lt;li&gt;Burnout and Privilege:&lt;/li&gt;
&lt;li&gt;Impact of Burnout on Software Engineers:&lt;/li&gt;
&lt;li&gt;Recognizing Developer Burnout:&lt;/li&gt;
&lt;li&gt;Preventing Developer Burnout:&lt;/li&gt;
&lt;li&gt;Closing the Brackets: A Burnout-Free Developer Journey&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you ever felt so drained that even the thought of starting a task feels overwhelming? If so, you might be familiar with burnout. But did you know that the term "burnout" has existed since Shakespeare's time in the 1600s? It's not just a modern-day buzzword. In fact, in 2019, the World Health Organization (WHO) officially recognized burnout as a syndrome stemming from unmanaged chronic workplace stress.&lt;/p&gt;

&lt;p&gt;Imagine feeling utterly exhausted, mentally distanced from your job, and developing a sense of cynicism towards your daily tasks. Add to that a feeling that you're not accomplishing enough no matter how hard you work. That's burnout in a nutshell. And while it can affect anyone in any profession, it's particularly prevalent in high-stress fields like software development.&lt;/p&gt;

&lt;p&gt;You might wonder why we're discussing burnout in a tech-focused blog. The reason is simple: understanding burnout is crucial in today's fast-paced digital world. As technology evolves at breakneck speeds, developers and IT professionals are often at the forefront, bearing the brunt of the pressure. Recognizing the signs of burnout and knowing how to address them can make a difference in your professional and personal life.&lt;/p&gt;

&lt;p&gt;In this blog series, we'll delve deeper into the causes of developer burnout, its impact, and, most importantly, strategies to prevent it. So, stay tuned whether you're a developer feeling the weight of burnout or a manager looking to support your team better. This series is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Developers Burn Out:
&lt;/h2&gt;

&lt;p&gt;Have you ever wondered why, despite your passion for coding and creating, there are days when you feel like you're running on empty? You're not alone. Many developers, just like you, experience burnout, and it's essential to understand the root causes to address it effectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Internal Factors:&lt;/strong&gt; Your personality and individual traits play a significant role in how you handle stress. Let's explore some of these internal factors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Idealistic Expectations:&lt;/strong&gt; Do you often set the bar incredibly high for yourself? While aiming for perfection can lead to outstanding results, it can also set you up for constant feelings of inadequacy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Need to Please:&lt;/strong&gt; If you're constantly putting others' needs before your own, you might be suppressing your desires and feelings. Over time, this can lead to resentment and burnout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Work as the Sole Purpose:&lt;/strong&gt; Passion for your job is fantastic, but if you view work as the only meaningful activity, you're missing out on relaxation and other fulfilling experiences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Overcommitment:&lt;/strong&gt; Taking on too many tasks? If you're constantly overburdened, it's a direct ticket to burnout. Remember, it's okay to say no sometimes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;External Factors:&lt;/strong&gt; The environment you work in significantly influences your mental well-being. Here are some external triggers for burnout:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Demanding Workload:&lt;/strong&gt; Continuous tight deadlines and an ever-growing to-do list? A relentless workload can quickly lead to exhaustion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leadership Issues:&lt;/strong&gt; Management's lack of support or understanding can make you feel isolated and undervalued.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Toxic Work Atmosphere:&lt;/strong&gt; A hostile environment with office politics or unsupportive colleagues can drain your energy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lack of Autonomy:&lt;/strong&gt; Feeling like you have little control over your projects or decisions can lead to feelings of helplessness.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stagnation:&lt;/strong&gt; Not growing professionally? A lack of development opportunities can make you feel stuck and fulfilled.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Recognizing these factors is the first step. In this blog series, we'll dive deeper into strategies to combat them and ensure you remain passionate, energized, and effective in your role.&lt;/p&gt;

&lt;h2&gt;
  
  
  Burnout in the Age of COVID-19:
&lt;/h2&gt;

&lt;p&gt;The COVID-19 pandemic has reshaped the world in ways we could never have anticipated. For many of you, it meant adjusting to remote work, juggling personal and professional responsibilities, and facing an uncertain future. But did you know that this global crisis has profoundly impacted developer burnout?&lt;/p&gt;

&lt;p&gt;Imagine this: Before the pandemic, you clearly separated your workspace and your personal space. Your living room or bedroom might double as your office. The boundaries have blurred, and so has the distinction between work hours and emotional time.&lt;/p&gt;

&lt;p&gt;You're not alone in feeling the weight of these changes. A staggering 81% of developers have reported experiencing burnout due to the pandemic. But why is this number so high?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increased Workloads:&lt;/strong&gt; With businesses pivoting to digital platforms, the demand for new software, apps, and systems skyrocketed. This might have meant more extended hours, tighter deadlines, and higher expectations for you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inefficient Processes:&lt;/strong&gt; Remote work brought its own set of challenges. Maybe you needed help with communication tools, faced connectivity issues, or missed the ease of turning to a colleague for a quick chat about a project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unclear Goals:&lt;/strong&gt; With companies navigating uncharted waters, goals and targets might have shifted frequently. For you, this could mean constantly changing priorities, making it hard to focus and deliver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Isolation:&lt;/strong&gt; Let's face it: working from home can be lonely. The lack of social interactions, team lunches, and face-to-face meetings can affect mental well-being.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Blurred Boundaries:&lt;/strong&gt; When your home becomes your office, it's challenging to 'switch off.' You might find yourself checking emails late at night or working through weekends, leading to burnout.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But here's the silver lining: Recognizing these challenges is the first step toward addressing them. In the upcoming sections, we'll explore strategies to help you navigate these unprecedented times, ensuring you stay motivated, productive, and, most importantly, mentally healthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Burnout and Privilege:
&lt;/h2&gt;

&lt;p&gt;When discussing burnout, especially in the tech industry, it's crucial to recognize the elephant in the room: privilege. You might wonder, "What does privilege have to do with burnout?" Let's dive in.&lt;/p&gt;

&lt;p&gt;Burnout doesn't discriminate; it can affect anyone, regardless of background or position. However, the resources and support available to combat burnout aren't equally accessible to everyone. This is where privilege comes into play.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access to Mental Health Resources:&lt;/strong&gt; If you're in a position where you can take a day off, seek therapy, or even take a vacation to recharge, you have a privilege many don't. For countless developers, especially those in freelance or contract positions, taking time off isn't an option. They might need more financial means or job security to prioritize their mental well-being.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexible Work Hours:&lt;/strong&gt; The luxury of setting your hours or taking breaks when needed is a privilege. Many developers work in environments with rigid schedules, tight deadlines, and little room for flexibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supportive Work Environment:&lt;/strong&gt; Having a supportive team and understanding managers is a privilege. If you can voice your concerns, ask for reduced workloads, or discuss mental health openly, you're in a better position than many.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Personal Circumstances:&lt;/strong&gt; Beyond the workplace, unique situations play a significant role. The road to burnout can be much shorter if you're a primary caregiver, facing financial stress, or dealing with personal challenges.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, why is it essential for you to recognize this privilege? Because understanding leads to empathy. Knowing your advantages, you can be more understanding and supportive of colleagues with different resources. It fosters a more inclusive, empathetic, and supportive work environment.&lt;/p&gt;

&lt;p&gt;Moreover, for those in leadership roles, recognizing these disparities is the first step toward creating a more equitable workspace. It's about ensuring every team member has the tools and support to thrive without burning out, regardless of their background or circumstances.&lt;/p&gt;

&lt;p&gt;In the end, addressing burnout isn't just about individual well-being; it's about creating a more inclusive, understanding, and supportive tech community for everyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impact of Burnout on Software Engineers:
&lt;/h2&gt;

&lt;p&gt;Have you ever felt like you're just going through the motions at work? Or have you noticed that the code you once wrote with passion and precision now feels like a chore? If these feelings resonate with you, you're not alone. The impact of burnout on software engineers is profound and far-reaching.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decreased Productivity:&lt;/strong&gt; You might find that tasks that once took you an hour drag on for days. Burnout can sap your energy, making even the simplest tasks feel insurmountable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduced Code Quality:&lt;/strong&gt; When you're mentally exhausted, the quality of your code can suffer. You might make more errors, overlook crucial details, or need help with needing help with problem-solving.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mental and Physical Health Issues:&lt;/strong&gt; Burnout isn't just a state of mind. It can manifest physically, leading to sleep disturbances, headaches, or even more severe health concerns. Mentally, it can pave the way for anxiety, depression, and feelings of hopelessness.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decreased Job Satisfaction:&lt;/strong&gt; Remember your excitement when you first started coding? Burnout can dim that spark. You might start questioning your career choices or even contemplate leaving the tech industry altogether.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strained Team Dynamics:&lt;/strong&gt; Burnout doesn't just affect you; it impacts your entire team. Being constantly tired or irritable can strengthen colleague relationships, leading to a cohesive team dynamic.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You might wonder, "Why are software engineers so susceptible to burnout?" With its rapid advancements and ever-evolving nature, the tech industry places immense pressure on developers. You're often racing against tight deadlines, grappling with new technologies, and navigating the complexities of team projects. Add to this the high expectations to deliver flawless code, and it's a recipe for burnout.&lt;/p&gt;

&lt;p&gt;But here's the good news: Recognizing the impact of burnout is the first step toward addressing it. In the upcoming sections of this blog series, we'll explore actionable strategies to combat burnout and reignite your passion for coding.&lt;/p&gt;

&lt;p&gt;Stay with me because together, we'll navigate this journey from burnout to balance, ensuring you continue to thrive as a software engineer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recognizing Developer Burnout:
&lt;/h2&gt;

&lt;p&gt;Have you ever had one of those days where you stare blankly at your screen, your mind wandering everywhere but your code? Or you've noticed you're more irritable, snapping at colleagues over minor issues. These might not just be 'off days.' They could be signs that you're on the path to burnout.&lt;/p&gt;

&lt;p&gt;Recognizing burnout early is crucial, not just for your well-being but also for your career. Let's delve into some telltale signs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Missed Deadlines:&lt;/strong&gt; It might be more than a busy phase if you're consistently missing deadlines or struggling to keep up with your workload. It could be an early warning sign of burnout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loss of Motivation:&lt;/strong&gt; Remember the thrill you felt when cracking a complex code or designing a new feature? Take note if that excitement has waned and tasks feel more like burdens.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increased Absenteeism:&lt;/strong&gt; Are you calling in sick more often? Or perhaps you're taking 'mental health days' to cope? Regularly needing time off can be an indicator that you're nearing burnout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Errors and Oversights:&lt;/strong&gt; If you're making more mistakes than usual or overlooking crucial details in your code, it's a sign that stress and fatigue might impact your cognitive functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Emotional Exhaustion:&lt;/strong&gt; Feeling drained, irritable, or detached from your work and colleagues? Emotional exhaustion is a hallmark of burnout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoidance:&lt;/strong&gt; If you're procrastinating more, avoiding team meetings, or even dreading logging into work, it's time to pause and reflect.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You might think, "But isn't this just part and parcel of a demanding job?" While the tech industry is undoubtedly challenging, continuously feeling this way isn't the norm. It would help if you differentiated between the usual work stress and the more severe symptoms of burnout.&lt;/p&gt;

&lt;p&gt;Why is early recognition so vital? Because the sooner you identify these signs, the quicker you can take steps to address them. Ignoring these symptoms can lead to more severe consequences for your mental health and career.&lt;/p&gt;

&lt;p&gt;In the following sections, we'll delve into actionable strategies to help you combat burnout. But for now, take a moment to reflect. If you see yourself in any of these signs, know it's okay to seek help or step back. After all, recognizing the problem is the first step to finding a solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preventing Developer Burnout:
&lt;/h2&gt;

&lt;p&gt;If you've ever felt the creeping symptoms of burnout, you know it's not a place you want to revisit. But how do you ensure that you stay energized, motivated, and passionate about your work as a developer? Prevention is critical, and I'm here to guide you through some proactive steps you can take.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Regular Check-ins:&lt;/strong&gt; It's essential to have open communication with your team and leadership. By regularly discussing your workload, challenges, and feelings, you can address potential issues before they escalate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set Healthy Work Boundaries:&lt;/strong&gt; Just because you can work anytime doesn't mean you should. Set specific work hours and stick to them. When your workday ends, truly disconnect. This means no checking emails or tweaking code late into the night.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Invest in Yourself:&lt;/strong&gt; Remember, you're not just a developer but a person with diverse interests and needs. Take time to pursue hobbies, learn new skills, or relax. Investing in personal growth and self-care can act as a buffer against burnout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Team Retreats and Special Events:&lt;/strong&gt; Building solid relationships with colleagues can make work more enjoyable. Consider organizing or participating in team retreats, workshops, or casual get-togethers. These events can foster camaraderie and provide a much-needed break from routine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Align with Your Strengths:&lt;/strong&gt; Ensure your role aligns with your natural abilities and passions. If you love front-end development but are stuck in back-end tasks, it might be time to chat with your manager. Working on projects that ignite your passion can keep burnout at bay.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seek Feedback:&lt;/strong&gt; Regular feedback can help you gauge your performance and address any areas of concern. Constructive feedback can boost your confidence and clarify, ensuring you're on the right track.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prioritize Mental Health:&lt;/strong&gt; This can't be stressed enough. If you're feeling overwhelmed, it's okay to seek help. Whether through therapy, meditation, or simply talking to someone you trust, prioritizing your mental well-being is crucial.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stay Active:&lt;/strong&gt; Physical activity can be a great stress reliever. Whether it's a quick walk during your lunch break, a morning jog, or a yoga session, staying active can boost your mood and energy levels.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember, preventing burnout isn't just about avoiding negative experiences; it's about creating a positive, fulfilling work environment. By implementing these strategies, you're safeguarding yourself against burnout and setting the stage for a thriving, successful career in development.&lt;/p&gt;

&lt;p&gt;In the upcoming sections, we'll delve deeper into these strategies, providing actionable insights and tools to ensure you stay at the top of your game. So, please stick with me because together, we'll navigate the path to a balanced, fulfilling developer life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing the Brackets: A Burnout-Free Developer Journey
&lt;/h2&gt;

&lt;p&gt;As we wrap up this segment of our deep dive into developer burnout, I want you to take a moment and reflect. Think about the countless hours you've poured into your projects, the late nights, the challenges overcome, and the successes celebrated. You've come a long way, and ensuring that the journey ahead is sustainable, fulfilling, and free from the shadows of burnout is essential.&lt;/p&gt;

&lt;p&gt;Burnout isn't just a buzzword or a fleeting feeling; it's a very real challenge that many developers, perhaps even you, face in today's fast-paced tech landscape. But with awareness comes empowerment. By understanding the signs, causes, and preventive measures, you're arming yourself with the tools to navigate the demanding world of software development with resilience and vigor.&lt;/p&gt;

&lt;p&gt;Remember, it's okay to ask for help, to set boundaries, and to prioritize your well-being. Your skills, passion, and dedication are invaluable to your organization and the broader tech community. And to harness that potential to its fullest, it's crucial to ensure that you're mentally and emotionally at your best.&lt;/p&gt;

&lt;p&gt;As we continue this series, we'll delve deeper into actionable strategies, tools, and resources to help you thrive in your role. Because at the end of the day, it's not just about writing code; it's about creating, innovating, and making a difference, all while ensuring you're happy, healthy, and motivated.&lt;/p&gt;

&lt;p&gt;Stay tuned, and together, let's chart a path to a balanced and burnout-free developer journey.&lt;/p&gt;

&lt;p&gt;Feel free to share your stories of burnout in the comments. It helps to vent; trust me.&lt;/p&gt;

</description>
      <category>mentalhealth</category>
      <category>worklifebalance</category>
      <category>burnout</category>
    </item>
    <item>
      <title>The New Era of C# Learning: Microsoft's Foundational C# Certification with freeCodeCamp</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Tue, 29 Aug 2023 14:10:32 +0000</pubDate>
      <link>https://forem.com/programazing/the-new-era-of-c-learning-microsofts-foundational-c-certification-with-freecodecamp-ccj</link>
      <guid>https://forem.com/programazing/the-new-era-of-c-learning-microsofts-foundational-c-certification-with-freecodecamp-ccj</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What is the Foundational C# Certification?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why Pursue This Certification?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Features of the Certification&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How to Earn the Certification&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Additional Training Opportunities&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The C# Challenge: Beyond Certification&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;What is the C# Challenge?&lt;/li&gt;
&lt;li&gt;Why Participate?&lt;/li&gt;
&lt;li&gt;How to Get Started?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discussion on the Impact on the Community:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Engaging with the C# Community: Your Next Steps&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
Closing Brackets: The Future of C# and Your Place in It

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Why C# Matters Now More Than Ever&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've been looking for ways to elevate your programming skills or dive into the world of C#, I have some thrilling news. Microsoft, synonymous with innovation and quality in tech, has just announced its brand-new &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-foundational-csharp-certification/"&gt;&lt;strong&gt;Foundational C# Certification&lt;/strong&gt;&lt;/a&gt;. And the best part? They've collaborated with freeCodeCamp, a charity renowned for offering top-notch, free learning resources in math, programming, and computer science.&lt;/p&gt;

&lt;p&gt;Why is this announcement creating such a buzz in the developer community? Well, let's break it down. C# has been a cornerstone in programming, pivotal in creating dynamic web applications, Unity games, and comprehensive enterprise solutions. As the tech landscape continues to evolve at a breakneck pace, having a tangible testament to your skills can be a game-changer. This certification isn't just a piece of paper or a digital badge; it reflects the time, effort, and passion you've poured into mastering this versatile language.&lt;/p&gt;

&lt;p&gt;But why should &lt;em&gt;you&lt;/em&gt; consider this certification? For starters, it's completely free. Yes, you read that right; in a world where quality education often comes with a hefty price tag, Microsoft and freeCodeCamp ensure that money isn't a barrier to accessing top-tier learning resources. This certification is globally available, meaning wherever you are, from New York to New Delhi, you can access this course and showcase your prowess in C#.&lt;/p&gt;

&lt;p&gt;Moreover, the Foundational C# Certification isn't just about theory. It offers a comprehensive 35-hour C# training course hosted on Microsoft Learn, ensuring you get a mix of theoretical knowledge and practical skills. So, whether you're an aspiring developer looking to make a mark or a seasoned professional aiming to upskill, this certification has something for everyone.&lt;/p&gt;

&lt;p&gt;In the coming sections, we'll delve deeper into the nuances of this certification, its features, and how you can embark on this enlightening journey. But for now, please take a moment and reflect on this opportunity. In a rapidly changing tech world, staying updated and proving your mettle is crucial. With this certification, you're not just adding a credential to your portfolio; you're making a statement about your commitment to growth, learning, and excellence in C#.&lt;/p&gt;

&lt;p&gt;Stay tuned, and let's explore this exciting venture together!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is the Foundational C# Certification?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Building on our excitement, let's delve deeper into what this Foundational C# Certification truly entails. After all, with such a promising introduction, you must wonder what's in store for you.&lt;/p&gt;

&lt;p&gt;This certification is the brainchild of a powerful collaboration between Microsoft and freeCodeCamp. For those of you who've been in the tech education space, you'll recognize freeCodeCamp as a beacon of free, high-quality programming education. Combine that with Microsoft's renowned expertise, and you're looking at a learning experience that's second to none.&lt;/p&gt;

&lt;p&gt;Now, let's talk specifics. The certification offers a comprehensive 35-hour C# training course, meticulously curated and hosted on Microsoft Learn. This isn't just a brief overview; it's a deep dive into the world of C#. This course ensures you can tackle any C# challenge, from foundational concepts to intricate syntax and real-world software development applications.&lt;/p&gt;

&lt;p&gt;But what truly sets this certification apart is its accessibility. No matter where you are, this course is available to you. And the best part? It's entirely free. That's right: top-tier education, expertly crafted content, and global reach, all without cost.&lt;/p&gt;

&lt;p&gt;This certification isn't just about acquiring knowledge and empowering you. It's a testament to your dedication and passion for coding. As we navigate through the rest of this post, we'll explore the myriad benefits, features, and the tangible impact this certification can have on your coding journey.&lt;/p&gt;

&lt;p&gt;Stay with me because there's so much more to uncover!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Pursue This Certification?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Continuing our exploration, you might wonder, "Why should I pursue this certification? What sets it apart in the vast sea of courses and certifications available?" Let's address those very valid questions.&lt;/p&gt;

&lt;p&gt;Firstly, C# isn't just another programming language; it's a powerhouse. In today's tech-driven world, C# plays a pivotal role in everything from dynamic web applications to Unity games and expansive enterprise solutions. By mastering C#, you're not just adding a skill to your repertoire but opening doors to many opportunities in the tech industry.&lt;/p&gt;

&lt;p&gt;While passion and skill are integral, having tangible proof of your expertise can be a game-changer. This is where the Foundational C# Certification shines. It's not merely a certificate; it's a testament to the hours, dedication, and passion you've invested. In a competitive job market, this certification can be the edge that sets you apart. Whether you're networking, job hunting, or freelancing, flashing this certification is bound to turn heads.&lt;/p&gt;

&lt;p&gt;But it's not just about recognition. It's about quality. Partnering with freeCodeCamp ensures that this isn't just another run-of-the-mill certification. It's a mark of quality education. Think of it as a seal of approval, guaranteeing that you've been trained with some of the best resources available. And remember, it's comprehensive, globally accessible, and free. This trifecta ensures that you and learners everywhere can benefit from top-tier C# training without barriers.&lt;/p&gt;

&lt;p&gt;Lastly, let's talk about growth. The tech landscape is ever-evolving, and continuous learning is critical to stay relevant. Pursuing this certification signals your expertise in C# and commitment to growth, adaptability, and staying ahead of the curve.&lt;/p&gt;

&lt;p&gt;In the sections to come, we'll delve into the nitty-gritty of the certification, its features, and how you can embark on this journey. But for now, I hope you're seeing the immense value and potential this certification holds for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Features of the Certification&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As we journey further into the depths of this exciting certification, you're probably eager to uncover the specifics. What exactly does the Foundational C# Certification offer you, and why is it a cut above the rest? Let's dive in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thorough Knowledge Base:&lt;/strong&gt; This needs to be a surface-level overview. The certification offers a comprehensive 35-hour training course, ensuring you grasp every facet of C#. It's all meticulously covered, from the core concepts and syntax to real-world software development applications. You'll have a holistic understanding by the end, ready to tackle any C# project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Credential to Flaunt:&lt;/strong&gt; Your online presence matters in today's digital age. Whether it's LinkedIn, a personal portfolio, or any other platform, showcasing this certification is a testament to your dedication and expertise. It's not just a badge; it's a beacon, signaling your commitment to continuous learning and mastery in C#.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global and Free:&lt;/strong&gt; Quality education should be free of geographical constraints or hefty price tags. This certification ensures just that. No matter where you are, this course is accessible to you. And the cherry on top? It's entirely free. This ensures that every developer, irrespective of their location or financial situation, can benefit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Comprehensive C# Journey:&lt;/strong&gt; The collaboration with freeCodeCamp is the secret sauce here. By leveraging resources from a world-class learning platform, you're guaranteed a learning experience that's both thorough and top-tier. And it doesn't end with just the training. The certification culminates in an 80-question exam, ensuring you've internalized everything you've learned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Community and Support:&lt;/strong&gt; Embarking on this journey doesn't mean you're alone. With a vibrant community backing you, there's always help around the corner. Whether it's doubts, discussions, or simply sharing experiences, you're joining a global community of like-minded learners.&lt;/p&gt;

&lt;p&gt;The Foundational C# Certification is more than just a course; it's a holistic experience. It's designed with you in mind, ensuring you learn, thrive, and excel in C#.&lt;/p&gt;

&lt;p&gt;As we progress through this blog, we'll explore how you can get started, the additional resources at your disposal, and much more. But for now, I hope you're as excited as I am about this certification's potential for your growth and future.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How to Earn the Certification&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Navigating the certification path can sometimes feel like a maze. But don't fret! I'm here to guide you step-by-step, ensuring you know how to embark on this transformative journey and earn that coveted Foundational C# Certification. Ready? Let's chart out your roadmap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Begin at the Source:&lt;/strong&gt; Head to the &lt;a href="https://www.freecodecamp.org/learn/foundational-c-sharp-with-microsoft/"&gt;Foundational C# Certification path on freeCodeCamp&lt;/a&gt;. This is your starting point, where you'll find all the training content neatly categorized under 'Courses'.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dive into the Modules:&lt;/strong&gt; Each course is broken down into modules. Click on each one to access the training content specific to that module. Think of these as chapters in a book, each building on the previous, guiding you seamlessly through the world of C#.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Engage with Microsoft Learn:&lt;/strong&gt; The training content is hosted on Microsoft Learn. If you've previously completed any of the content, there's no need to redo it. However, if you're new, immerse yourself fully. Remember, it's not about rushing through but genuinely understanding and internalizing the concepts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Your Understanding:&lt;/strong&gt; After each module, there's a comprehension check question on freeCodeCamp. This is your checkpoint, ensuring you've grasped the essence of that module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collect Your Trophies:&lt;/strong&gt; Completing each course earns you a Trophy on Microsoft Learn. But it's not just about collecting these; each Trophy has instructions on freeCodeCamp to claim and submit them. It's like a mini-reward system, keeping you motivated throughout your journey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Final Challenge:&lt;/strong&gt; Once you've navigated through all the training, it's time for the ultimate test - the exam. This 80-question challenge will test everything you've learned, ensuring you're ready to wear the badge of C# expertise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Celebrate Your Achievement:&lt;/strong&gt; You earn the Foundational C# Certification after successfully clearing the exam. It's not just a digital badge; it's a testament to your hard work, dedication, and passion for C#.&lt;/p&gt;

&lt;p&gt;While this roadmap might seem straightforward, remember that the journey is as important as the destination. Engage with the content, participate in discussions, seek help when in doubt, and most importantly, enjoy the process. Learning C# through this certification is not just about adding a skill; it's about growing as a developer and joining a global community of C# enthusiasts.&lt;/p&gt;

&lt;p&gt;In the upcoming sections, we'll delve into additional resources, community support, and more to ensure you're well-equipped. But for now, take a deep breath, gear up, and embark on this exciting path to C# mastery.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Additional Training Opportunities&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While the Foundational C# Certification offers a robust learning experience, I understand that sometimes you crave more. It could be a deeper dive into specific topics or the camaraderie of learning alongside peers. Whatever your motivation, I've got some fantastic news for you. There are additional training opportunities to complement your learning journey, ensuring you're not just well-informed but genuinely immersed in the world of C#.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interactive Sessions with Microsoft:&lt;/strong&gt; Beyond the structured content on Microsoft Learn, they're hosting a series of office-hour-style streaming events. Picture this: live sessions where expert presenters review training courses, walk you through guided projects, and here's the best part answer your burning questions. Scheduled from September 20 to October 25, every Wednesday at 2:00 p.m. UTC, these sessions are a goldmine for interactive learning. And if you can't catch them live, don't worry. All sessions will be available on-demand via the &lt;a href="https://www.youtube.com/@dotnet"&gt;.NET YouTube channel&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dive Deeper with freeCodeCamp:&lt;/strong&gt; Starting with a comprehensive video walkthrough, freeCodeCamp offers insights into the certification and training journey. But that's not all. The vibrant freeCodeCamp community awaits you in the C# section of their forum. Whether you're stuck on a tricky concept, seeking feedback on a project, or want to discuss the latest C# trends, this community is your go-to hub.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Challenges and More:&lt;/strong&gt; Beyond the structured learning, there's the thrill of challenges. The C# Challenge, kicking off on August 29th, is your chance to test your skills, compare your learning journey with global peers, and earn some bragging rights. It's not just about knowledge; it's about application, innovation, and friendly competition.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You might wonder, "Why should I engage with these additional resources?" The answer is simple: holistic learning. While the certification offers a solid foundation, these additional opportunities ensure you're genuinely immersed, constantly challenged, and continually growing. They provide different perspectives, hands-on experiences, and the invaluable chance to interact with experts and peers alike.&lt;/p&gt;

&lt;p&gt;As we continue to navigate this blog, we'll explore more facets of the C# world, ensuring you're equipped with all the tools, resources, and knowledge to excel truly. But for now, I encourage you to tap into these additional training opportunities. Dive in, engage, and let your passion for C# shine even brighter.&lt;/p&gt;

&lt;p&gt;Stay with me because our C# adventure is far from over!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The C# Challenge: Beyond Certification&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Having delved deep into the certification and the plethora of training opportunities, you might think, "What's next?" Well, for those with a competitive streak and a thirst for pushing boundaries, I present The C# Challenge to you. Let's dive into what this entails and why it's the perfect next step in your C# journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the C# Challenge?
&lt;/h2&gt;

&lt;p&gt;Beyond the structured learning and certification, the C# Challenge is your playground. Kicking off on August 29th, it's a unique opportunity to apply what you've learned, test your skills, and see where you stand amongst global peers. Think of it as a marathon, where instead of miles, you're navigating through coding challenges, each designed to test, tease, and tantalize your C# skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Participate?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Skill Application:&lt;/strong&gt; It's one thing to learn, but applying that knowledge in real-world scenarios? That's where true mastery shines. The C# Challenge offers a plethora of tasks and problems, ensuring you're not just recalling what you've learned but truly applying it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global Benchmarking:&lt;/strong&gt; Have you ever wondered how you stack up against other C# enthusiasts globally? This challenge is your chance. It's not about competition but understanding where you shine and areas you can further hone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuous Learning:&lt;/strong&gt; The tech world and the realm of C# are ever-evolving. The C# Challenge ensures you're always on your toes, adapting, learning, and growing with each task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Community and Collaboration:&lt;/strong&gt; While challenging, it celebrates the C# community. Engage with participants, discuss solutions, share insights, and build connections. After all, learning is always better when shared.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Get Started?
&lt;/h2&gt;

&lt;p&gt;Dive right in! Register here and mark your calendars. Whether aiming for the top spot or just looking to learn and engage, the C# Challenge promises a fulfilling experience.&lt;/p&gt;

&lt;p&gt;The Foundational C# Certification is just the beginning. With the additional training opportunities and the C# Challenge, you're looking at a holistic, enriching journey in C#. So, gear up, dive in, and make the most of this adventure together.&lt;/p&gt;

&lt;p&gt;And remember, whether it's the certification, the live sessions, or the challenge, it's all about the journey, the learning, and the passion for C#. Stay with me as we explore more facets and opportunities in the upcoming sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Discussion on the Impact on the Community:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As we've journeyed through the intricacies of the Foundational C# Certification and the myriad of opportunities it presents, it's crucial to pause and reflect on its broader implications. How does this certification impact the global C# community? What ripples does it send across the vast ocean of seasoned and new developers? Let's dive into this discussion, weighing the positives and potential concerns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Bright Side: The Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Democratizing Education:&lt;/strong&gt; The collaboration between Microsoft and freeCodeCamp ensures that quality C# education is accessible to all, irrespective of geographical or financial barriers. This move democratizes learning, providing that every aspiring C# developer, regardless of background, has a shot at excellence.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quality Assurance:&lt;/strong&gt; With freeCodeCamp's reputation for delivering top-notch content, this certification isn't just a badge; it's a mark of quality. For employers, it is a reliable indicator of a candidate's skills and dedication to the craft.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fostering Community Growth:&lt;/strong&gt; The certification, additional training opportunities, and the C# Challenge encourage community engagement. It's about individual growth and elevating the community, fostering collaboration, discussions, and shared learning experiences.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Other Side: Potential Concerns&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Over Saturation:&lt;/strong&gt; With the certification being globally available and accessible, there's a potential risk of it becoming too ubiquitous. Does it dilute its value in the job market if everyone has it?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Online Learning Limitations:&lt;/strong&gt; While online courses offer flexibility and accessibility, there's a debate about their effectiveness in gauging a developer's skills. Hands-on experience, teamwork, and real-world problem-solving might need to be fully captured.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keeping Content Updated:&lt;/strong&gt; The tech world is ever-evolving. Ensuring the certification content remains updated and in sync with industry demands will be crucial. Otherwise, there's a risk of it becoming obsolete or out-of-touch.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While we've discussed the broader implications, it's essential to remember that the community comprises individuals like you. Your engagement, feedback, and active participation can shape the direction and impact of such initiatives. Embrace the certification, engage in discussions, share feedback, and ensure it remains a valuable asset.&lt;/p&gt;

&lt;p&gt;The Foundational C# Certification is a monumental step with the potential to reshape the landscape of C# education and community engagement. While its benefits are numerous, it's essential to remain aware of potential concerns and work collectively to address them.&lt;/p&gt;

&lt;p&gt;As we continue to navigate the world of C#, remember that every tool, certification, or resource is as impactful as the community makes it. Let's harness this opportunity, shape its impact, and ensure it remains a beacon of excellence for all C# enthusiasts.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Engaging with the C# Community: Your Next Steps&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As we continue our journey through the expansive world of C#, I want to spotlight an often-overlooked yet invaluable aspect: the community. Beyond the code, beyond the certifications, lies a vibrant, passionate community of C# enthusiasts. And trust me, engaging with this community can be one of your most rewarding steps. Let's delve into why this matters and how you can dive right in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Power of Community&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collaborative Learning:&lt;/strong&gt; C# is vast, and no matter how seasoned you are, there's always something new to learn. Engaging with the community exposes you to diverse perspectives, solutions, and techniques. It's learning amplified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Networking Opportunities:&lt;/strong&gt; Whether you're looking for job opportunities, collaborations, or just some coding buddies, the C# community is a goldmine. It's not just about who you know but who you get to know.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Support and Guidance:&lt;/strong&gt; Stuck on a tricky piece of code? Need feedback on a project? Or just feeling overwhelmed? The community is here for you. It's a space of mutual support where every question, big or small, finds an answer.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Diving into the C# Community&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Forums and Discussion Boards:&lt;/strong&gt; Platforms like &lt;a href="https://stackoverflow.com/"&gt;Stack Overflow&lt;/a&gt; and the &lt;a href="https://www.freecodecamp.org/forum/c/csharp"&gt;C# section of freeCodeCamp's forum&lt;/a&gt; are bustling with activity. Ask, answer, discuss, and engage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Social Media Groups:&lt;/strong&gt; Platforms like LinkedIn, Facebook, and Reddit have dedicated C# groups. Join them for news, updates, discussions, and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Local Meetups:&lt;/strong&gt; Websites like &lt;a href="http://Meetup.com"&gt;Meetup.com&lt;/a&gt; often host C# and .NET meetups. It's a chance to meet fellow enthusiasts, attend workshops, and participate in coding sessions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contribute to Open Source:&lt;/strong&gt; Platforms like &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt; have numerous C# projects. Contribute, collaborate, and learn in real time. Plus, it's a fantastic way to build your portfolio.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attend Conferences:&lt;/strong&gt; Events like &lt;a href="https://www.dotnetconf.net/"&gt;.NET Conf&lt;/a&gt; are not just about learning; they're about immersing yourself in the community. Network, attend workshops, and stay updated with the latest in C#.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember, the community is as much about giving as it is about receiving. Share your knowledge, offer support, and contribute actively. As you grow in your C# journey, you'll find that you're not just a member but an integral part of this vibrant community.&lt;/p&gt;

&lt;p&gt;Engaging with the C# community is more than just a step; it's a leap toward holistic growth. As we continue exploring the multifaceted world of C# in the coming sections, remember that you're not alone on this journey. A global community of passionate developers is right there with you every step of the way.&lt;/p&gt;

&lt;p&gt;Stay connected, stay engaged, and let's continue to explore the wonders of C# together!&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Brackets: The Future of C# and Your Place in It
&lt;/h2&gt;

&lt;p&gt;As we near the end of our deep dive into the world of C# and its many opportunities, I want to reflect on the bigger picture. The Foundational C# Certification, the additional training, and the C# Challenge are all pieces of a giant puzzle. A puzzle that paints a bright future for C# and, more importantly, for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why C# Matters Now More Than Ever&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;C# has firmly established itself as a cornerstone in the ever-evolving tech landscape. Its versatility is unmatched, from game development with Unity to enterprise solutions and dynamic web applications. As industries continue to digitize and the demand for seamless, efficient software solutions rises, C# developers will find themselves at the forefront of innovation.&lt;/p&gt;

&lt;p&gt;With the tools and resources we've discussed, you're not just a passive observer but an active participant. The Foundational C# Certification equips you with the knowledge, the additional training hones your skills, and the C# Challenge tests your mettle. Together, they shape you into a C# developer ready to tackle the challenges of tomorrow.&lt;/p&gt;

&lt;p&gt;The tech world doesn't stand still, and neither should you. Embrace the ethos of continuous learning. Stay curious, whether it's updated in C#, new programming paradigms, or emerging technologies. The resources we've explored are just a starting point; the learning journey is endless.&lt;/p&gt;

&lt;p&gt;So, where do you go from here? Dive in headfirst. Start with the certification, engage with the community, take on the challenge, and most importantly, keep that flame of passion burning. C# offers a world of opportunities, and with the tools at your disposal, you're poised to seize them.&lt;/p&gt;

&lt;p&gt;In the grand tapestry of the tech world, C# is a vibrant thread, and with the knowledge and skills you're acquiring, you're weaving your unique pattern. It's an exciting time to be a C# developer, and I'm thrilled to have shared this journey with you.&lt;/p&gt;

&lt;p&gt;Stay curious, stay passionate, and remember: the world of C# is vast and waiting for you to make your mark. Here's to many more coding adventures together!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The Art of Randomness in .NET 8: New Methods and Techniques</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Mon, 28 Aug 2023 17:12:06 +0000</pubDate>
      <link>https://forem.com/programazing/the-art-of-randomness-in-net-8-new-methods-and-techniques-1mga</link>
      <guid>https://forem.com/programazing/the-art-of-randomness-in-net-8-new-methods-and-techniques-1mga</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Traditional Randomness in .NET: The Old Ways&lt;/li&gt;
&lt;li&gt;.NET 8's Approach to Randomness: The New Methods&lt;/li&gt;
&lt;li&gt;Practical Examples: Old vs. New&lt;/li&gt;
&lt;li&gt;Closing Brackets: A Look Back at .NET's Progress&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you ever marveled at the unpredictability of a dice roll or the shuffle of a deck of cards? Randomness is pivotal in the programming world, much like that dice or deck of cards. Whether you're developing a game, securing data, or simply wanting to surprise your users with a random quote of the day, the ability to generate random numbers or sequences is crucial.&lt;/p&gt;

&lt;p&gt;If you've been working with .NET for a while, you're probably familiar with the classic &lt;code&gt;System.Random&lt;/code&gt; class. It's been our trusty tool for generating random numbers. And for those of you deeply invested in security, &lt;code&gt;System.Security.Cryptography.RandomNumberGenerator&lt;/code&gt; might ring a bell, ensuring cryptographic strength in randomness.&lt;/p&gt;

&lt;p&gt;But here's the exciting part: .NET 8 has introduced some game-changing methods that promise to redefine how we approach randomness. Imagine plugging a set of random items directly from a collection or shuffling data with just a single command. Sounds enticing, right?&lt;/p&gt;

&lt;p&gt;In this post, we'll embark on a journey, comparing the old ways of handling randomness in .NET with the fresh, streamlined methods of .NET 8. By the end, you'll appreciate the evolution of randomness in .NET and be equipped to harness these new tools in your projects.&lt;/p&gt;

&lt;p&gt;So, are you ready to dive into the art of randomness with .NET 8? Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional Randomness in .NET: The Old Ways
&lt;/h2&gt;

&lt;p&gt;Remember the first time you wanted to generate a random number in your application? If you're like most of us, you probably reached for the trusty &lt;code&gt;System.Random&lt;/code&gt; class. It's been the go-to for many developers over the years, and for good reason.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;System.Random&lt;/code&gt;, you could quickly generate random numbers within a specified range. Need a random integer between 1 and 10? No problem. How about a random double? &lt;code&gt;System.Random&lt;/code&gt; had you covered. It was simple, straightforward, and got the job done for most general purposes.&lt;/p&gt;

&lt;p&gt;But then, there were times when you needed something more robust, especially when security was at stake. Enter &lt;code&gt;System.Security.Cryptography.RandomNumberGenerator&lt;/code&gt;. This wasn't just any random number generator but designed with cryptographic strength. When you were working on applications where the quality of randomness could mean the difference between a secure system and a vulnerable one, this was your tool of choice. It ensured the generated numbers were unpredictable, making it a cornerstone for cryptographic operations.&lt;/p&gt;

&lt;p&gt;However, as with all tools, they weren't without their challenges. With &lt;code&gt;System.Random&lt;/code&gt;, there were concerns about its predictability, especially if not correctly initialized. And while &lt;code&gt;System.Security.Cryptography.RandomNumberGenerator&lt;/code&gt; offered better randomness, it came with more complexity, especially for newcomers.&lt;/p&gt;

&lt;p&gt;Moreover, both tools had their limitations. Want to select items from a collection or shuffle a list randomly? You'd have to craft your solutions, often relying on the generated random numbers as a base. It could have been more intuitive, and there was room for improvement.&lt;/p&gt;

&lt;p&gt;But here's the good news: .NET 8 recognized these challenges and saw the opportunity. The result? A set of new methods that promise to make working with randomness more intuitive and efficient than ever before.&lt;/p&gt;

&lt;p&gt;Before diving into these exciting new tools, we must appreciate where we've come from. The traditional methods served us well, laying the groundwork for the innovations we're about to explore. So, as we bid farewell to the old ways, let's gear up to embrace the future of randomness in .NET 8.&lt;/p&gt;

&lt;h2&gt;
  
  
  .NET 8's Approach to Randomness: The New Methods
&lt;/h2&gt;

&lt;p&gt;You know, there's something exhilarating about embracing change significantly when it simplifies our tasks and amplifies our efficiency. And that's precisely what .NET 8 offers with its new approach to randomness.&lt;/p&gt;

&lt;p&gt;First, let's talk about the &lt;code&gt;GetItems&amp;lt;T&amp;gt;()&lt;/code&gt; method. Gone are the days when you'd loop through a collection, using random numbers to pick items. With &lt;code&gt;GetItems&amp;lt;T&amp;gt;()&lt;/code&gt;, you can select a specified number of random items from a collection. Let's see it in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private static ReadOnlySpan&amp;lt;Button&amp;gt; allButtons = new[]

{

    Button.Red,

    Button.Green,

    Button.Blue,

    Button.Yellow,

};

Button[] randomButtons = Random.Shared.GetItems(allButtons, 3);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, you randomly select three buttons from the &lt;code&gt;allButtons&lt;/code&gt; collection. Simple, right?&lt;/p&gt;

&lt;p&gt;Next, we have the &lt;code&gt;Shuffle&amp;lt;T&amp;gt;()&lt;/code&gt; method. If you've ever tried to shuffle a list or an array in the past, you'd know it could have been more straightforward. But with .NET 8, shuffling becomes a breeze:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int[] numbers = { 1, 2, 3, 4, 5 };

Random.Shared.Shuffle(numbers);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, your &lt;code&gt;numbers&lt;/code&gt; array is shuffled in a random order. No more custom shuffle algorithms or complex logic. It's all baked right into .NET 8.&lt;/p&gt;

&lt;p&gt;But why does this matter to you? Well, these methods aren't just about convenience but efficiency and reliability. By leveraging these built-in methods, you're ensuring that the randomness is of high quality and reducing the chances of errors that might creep in with custom solutions.&lt;/p&gt;

&lt;p&gt;So, as you dive into your next project or revisit an old one, remember these tools. Embrace the new while appreciating the foundation laid by the old. With .NET 8, the world of randomness just got much more exciting, and you're at the forefront of it all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Examples: Old vs. New
&lt;/h2&gt;

&lt;p&gt;Let's take a walk down memory lane, shall we? Remember when you wanted to select items from a list randomly? The old approach might have looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;string&amp;gt; fruits = new List&amp;lt;string&amp;gt; { "Apple", "Banana", "Cherry", "Date" };

Random rand = new Random();

string randomFruit = fruits[rand.Next(fruits.Count)];

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It worked, but it required you to instantiate a &lt;code&gt;Random&lt;/code&gt; object and then use it to generate an index. Now, with .NET 8's &lt;code&gt;GetItems&amp;lt;T&amp;gt;()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string[] fruitsArray = { "Apple", "Banana", "Cherry", "Date" };

string[] selectedFruits = Random.Shared.GetItems(fruitsArray, 2);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You've randomly selected two fruits from the array in just two lines. The new method is not only concise but also inherently more readable.&lt;/p&gt;

&lt;p&gt;Now, let's talk shuffling. Previously, to shuffle a list, you might have used an algorithm like the Fisher-Yates shuffle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;int&amp;gt; numbers = Enumerable.Range(1, 5).ToList();

for (int i = numbers.Count - 1; i &amp;gt; 0; i--)

{

    int j = rand.Next(i + 1);

    int temp = numbers[i];

    numbers[i] = numbers[j];

    numbers[j] = temp;

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a classic algorithm, but it requires manual looping and swapping. Compare that to the new &lt;code&gt;Shuffle&amp;lt;T&amp;gt;()&lt;/code&gt; method in .NET 8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int[] numbersArray = { 1, 2, 3, 4, 5 };

Random.Shared.Shuffle(numbersArray);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference is night and day. With a single method call, your array is shuffled, saving you from the intricacies of custom algorithms.&lt;/p&gt;

&lt;p&gt;These examples highlight a fundamental shift in .NET 8's approach to randomness. It's not just about introducing new methods; it's about enhancing your developer experience. It's about ensuring that you spend less time on boilerplate code and more time crafting the core logic of your applications.&lt;/p&gt;

&lt;p&gt;So, remember these comparisons the next time you're faced with a randomness challenge. Embrace the simplicity and power of .NET 8, and let it elevate your coding journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Brackets: A Look Back at .NET's Progress
&lt;/h2&gt;

&lt;p&gt;As we wrap up this exploration into the world of randomness in .NET 8, please take a moment to reflect. Think about the countless times you've wrestled with generating random numbers, selecting random items, or shuffling lists. Remember the custom algorithms, the extra lines of code, and the occasional uncertainties?&lt;/p&gt;

&lt;p&gt;Now, with .NET 8, you're stepping into a new era. An era where randomness is not just a tool but an art form, refined and optimized for your convenience. The new methods, &lt;code&gt;GetItems&amp;lt;T&amp;gt;()&lt;/code&gt; and &lt;code&gt;Shuffle&amp;lt;T&amp;gt;()&lt;/code&gt;, are more than just additions to the framework; they're a testament to the evolution of .NET, constantly adapting and continually improving.&lt;/p&gt;

&lt;p&gt;But there's a broader message here beyond the technicalities and the code. It's about embracing change and innovation. It's about recognizing that, as developers, our journey is one of continuous learning and adaptation. Today, it's randomness in .NET 8. Tomorrow, it might be another feature in a different framework. But the essence remains the same: to grow, innovate, and create better solutions for our challenges.&lt;/p&gt;

&lt;p&gt;So, as you move forward, armed with the knowledge of these new methods, I encourage you to experiment, explore, and experience the art of randomness in .NET 8. Dive into your projects with renewed enthusiasm, knowing you have powerful tools at your fingertips. And remember, in the ever-evolving world of technology, you're not just a coder; you're an artist, painting with lines of code, and with .NET 8, your palette just got a little more vibrant.&lt;/p&gt;

&lt;p&gt;Thank you for joining me on this journey. Here's to many more adventures in the world of .NET!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>dotnetcore</category>
      <category>random</category>
    </item>
    <item>
      <title>Setting up SSH Keys for GitHub using WSL and Keychain</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Tue, 06 Dec 2022 05:00:44 +0000</pubDate>
      <link>https://forem.com/programazing/setting-up-ssh-keys-for-github-using-wsl-and-keychain-m83</link>
      <guid>https://forem.com/programazing/setting-up-ssh-keys-for-github-using-wsl-and-keychain-m83</guid>
      <description>&lt;p&gt;SSH keys are a secure and convenient way to authenticate with remote servers and services. This blog post will cover how to create SSH keys using the Keychain utility and then add the keys to GitHub.&lt;/p&gt;

&lt;p&gt;Though GitHub is mentioned, you can use this for any remote Git service such as GitLab, Bitbucket, or Gitea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Keychain
&lt;/h2&gt;

&lt;p&gt;To use Keychain, you'll need to install it on your system. On Ubuntu or other Debian-based systems, you can use the following command to install Keychain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install keychain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating SSH Keys
&lt;/h2&gt;

&lt;p&gt;After installing Keychain, you can use the ssh-keygen command to create your SSH keys. This command will prompt you for a file to save the keys and a passphrase to protect the keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen -t ed25519 -C "your_email@example.com"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted, enter a file in which to save the key (you can use the default location by pressing Enter) and enter a passphrase (this is an optional security measure that adds an extra layer of protection to your SSH key).&lt;/p&gt;

&lt;p&gt;Take a little time to think of something unique if you plan on having multiple SSH keys.&lt;/p&gt;

&lt;p&gt;I suggest using a system like [platform]-[user]-[PC]; Mine would like github-Programazing-WorkPC.&lt;/p&gt;

&lt;p&gt;Once your SSH key is generated, you can view it by typing the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat ~/.ssh/id_ed25519.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will be the contents of your public SSH key, which you will need to add to your GitHub account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the Keys to Keychain
&lt;/h2&gt;

&lt;p&gt;On Ubuntu or other Debian-based systems, you can run the following command to open your shell's login script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano .profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following to the bottom of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eval `keychain --agents ssh --eval ~/.ssh/yourSSHKey`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tip: If you're new to nano press &lt;code&gt;ctrl + s&lt;/code&gt; to save and &lt;code&gt;ctrl + x&lt;/code&gt; to exit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After saving and returning to the terminal, you'll want to exit the terminal.&lt;/p&gt;

&lt;p&gt;When you open the terminal again, Keychain will prompt you for your password.&lt;/p&gt;

&lt;p&gt;That's it! Keychain will act as a go-between and keep your keys added to the same &lt;code&gt;ssh-agent&lt;/code&gt; every session. You'll only have to enter the passwords again when you restart your computer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the SSH Key to GitHub
&lt;/h2&gt;

&lt;p&gt;Now that you have your SSH keys with Keychain, you can add the public key to GitHub to authenticate with the service.&lt;/p&gt;

&lt;p&gt;To do this, log in to your GitHub account and go to the "Settings" page. From there, click on the "SSH and GPG keys" tab and click the "New SSH key" button.&lt;/p&gt;

&lt;p&gt;Enter a name for the key in the "Title" field and then paste the contents of your public key file (located at ~/.ssh/id_ed25519.pub) into the "Key" field. Finally, click the "Add SSH key" button to add the key to your GitHub account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing your SSH Key
&lt;/h2&gt;

&lt;p&gt;Once you've added the key to GitHub, type the following into your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh -T git@github.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If successful, you should be greeted with the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hi UserName! You've successfully authenticated, but GitHub does not provide shell access.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If not, I'd suggest reading &lt;a href="[https://docs.github.com/en/authentication/troubleshooting-ssh](https://docs.github.com/en/authentication/troubleshooting-ssh)"&gt;GitHub's Troubleshooting Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By using Keychain, you can securely store your SSH keys and avoid having to enter the passphrase every time you use them. This allows for rapid development as you don't have to enter your SSH key whenever you want to push a change.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>ssh</category>
      <category>wsl</category>
    </item>
    <item>
      <title>Web Scraping and Generating PDFs Using C# and .NET</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Fri, 02 Dec 2022 04:50:09 +0000</pubDate>
      <link>https://forem.com/programazing/web-scraping-and-generating-pdfs-using-c-and-net-1d66</link>
      <guid>https://forem.com/programazing/web-scraping-and-generating-pdfs-using-c-and-net-1d66</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This blog post is part of the 2022 &lt;a href="https://csadvent.christmas/"&gt;C# Advent Calendar&lt;/a&gt;. Go check out the other 49 great posts after you read mine, of course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the most valuable things I've ever made is a simple web scraper that could generate PDFs and compare versions. I'm sure plenty of services will do this for a small fee, but I'd rather create a custom solution and save myself the cost.&lt;/p&gt;

&lt;p&gt;This idea started when I worked for a company that made digital versions of government forms. One of the most annoying parts of that job was that the government often updated records without notice. We usually relied on our clients to tell us when the government revised forms.&lt;/p&gt;

&lt;p&gt;I decided I wouldn't stay in the dark, so I created a simple application to let me know when things had changed. It had three primary functions; check if a known webpage or PDF had changed; if so, make a copy and save the current document in a versioned database. Eventually, I decided to add an email function, but I'm not going to include that in today's post.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;p&gt;You'll use three tools to help create this application, though it's only two.&lt;/p&gt;

&lt;p&gt;The first is AngleSharp, which will let you create a copy of a web page's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction"&gt;Document Object Model (DOM)&lt;/a&gt;. I recently upgraded to this from HtmlAgilityPack because it seemed easier to use.&lt;/p&gt;

&lt;p&gt;Next is MigraDocCore, built on top of PdfSharpCore and created by the same developer. They'll help you create PDF documents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package AngleSharp &lt;span class="nt"&gt;--version&lt;/span&gt; 0.17.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package PdfSharpCore &lt;span class="nt"&gt;--version&lt;/span&gt; 1.3.41
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package MigraDocCore.Rendering &lt;span class="nt"&gt;--version&lt;/span&gt; 1.3.41

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;First, create a model of the data you want to store. You could easily make this a Record, but some habits die hard for me.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Country
{
    public string? Name { get; set; }
    public string? Capital { get; set; }
    public string? Population { get; set; }
    public string? Area_KM_Squared { get; set; }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you'll set up AngleSharp to go out and fetch the DOM to manipulate.&lt;/p&gt;

&lt;p&gt;The two essential parts are the address and what you want to select from the DOM.&lt;br&gt;&lt;br&gt;
&lt;code&gt;var document = await context.OpenAsync("https://www.scrapethissite.com/pages/simple/");&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var countries =
document
.QuerySelectorAll("*")
.Where(e =&amp;gt; e.LocalName == "div" &amp;amp;&amp;amp; e.ClassName == "col-md-4 country")
.ToList();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above says select everything with a div and the class name "col-md-4 country" and place that in a list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class WebpageData
{
    public async Task&amp;lt;List&amp;lt;Country&amp;gt;&amp;gt; CountriesAsync()
    {
        var config = Configuration.Default.WithDefaultLoader();
        var context = BrowsingContext.New(config);
        var document = await context.OpenAsync("https://www.scrapethissite.com/pages/simple/");
        var countries = 
       document
       .QuerySelectorAll("*")
       .Where(e =&amp;gt; e.LocalName == "div" &amp;amp;&amp;amp; e.ClassName == "col-md-4 country")
       .ToList();

        List&amp;lt;Country&amp;gt; parsedCountries = new();
        foreach (var country in countries)
        {
            var lines = country
            .Text()
            .Split("\n")
            .Select(s =&amp;gt; s.Trim())
            .Where(s =&amp;gt; !string.IsNullOrWhiteSpace(s))
            .ToArray();

            parsedCountries.Add(new Country()
            {
                Name = lines[0].Trim(),
                Capital = lines[1].Split(':')[1].Trim(),
                Population = lines[2].Split(':')[1].Trim(),
                Area_KM_Squared = lines[3].Split(':')[1].Trim()
            });
        }

        var output = parsedCountries.OrderBy(c =&amp;gt; c.Name).ToList();
        return output;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where you'll transform &lt;code&gt;List&amp;lt;Country&amp;gt;&lt;/code&gt; into &lt;code&gt;PdfDocument&lt;/code&gt; within a static class helper. I prefer to use these when converting types or to return bools. It just makes things look cleaner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static PdfDocument ToPDF(this List&amp;lt;Country&amp;gt; input)
{
    Document document = new();

    Section section = document.AddSection();

    foreach (var item in input)
    {
        section.AddParagraph($"Name: {item.Name}");
        section.AddParagraph($"Capital: {item.Capital}");
        section.AddParagraph($"Population: {item.Population}");
        section.AddParagraph($"Area KM Squared: {item.Area_KM_Squared}");
        section.AddParagraph();
    }

    PdfDocumentRenderer pdfRenderer = new() { Document = document };

    pdfRenderer.RenderDocument();

    return pdfRenderer.PdfDocument;
}

public static bool IsTheSameAsLatestDBVersion(this PdfDocument input)
{
    var current = DB.GetCurrentDBVersion();

    if (input == current) { return true; }

    return false;
}
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where you'd connect to your database and pull a copy of the latest saved page. This is a cheeky way to make sure the two &lt;code&gt;PdfDocument&lt;/code&gt;s are different since our source data never really changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class DB
{
    public static PdfDocument GetCurrentDBVersion()
    {
        return new PdfDocument();
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything finally comes together in this simple section of code. All that happens here is that the current page is returned as a list, it's transformed into a PDF, compared to the last saved version, and if it's the same, the program exits. If it's not the same, a new PDF is created, and an entry in the database is made.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var result = new WebpageData().CountriesAsync().GetAwaiter().GetResult();

var pdf = result.ToPDF();

var pdfIsTheSameAsLatestDBVersion = pdf.IsTheSameAsLatestDBVersion();

if (pdfIsTheSameAsLatestDBVersion)
    return;

var todaysDate = DateTime.Now.Date.ToString("yyyy-MM-dd");
var filename = $"CountryData_{todaysDate}.pdf";
pdf.Save(filename);
// pdf.AddToDB();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This may seem like a simple tool, but I can't count the times I've found it helpful to be alerted to a change in a webpage or a PDF.&lt;/p&gt;

&lt;p&gt;If you found this helpful, let me know! If you have any suggestions or feedback, I'd love to hear it.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>pdf</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>Using DateOnly and TimeOnly in .NET 6 to Simplify Your Code</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Tue, 21 Dec 2021 05:00:00 +0000</pubDate>
      <link>https://forem.com/programazing/using-dateonly-and-timeonly-in-net-6-to-simplify-your-code-4h1l</link>
      <guid>https://forem.com/programazing/using-dateonly-and-timeonly-in-net-6-to-simplify-your-code-4h1l</guid>
      <description>&lt;p&gt;&lt;em&gt;Image by &lt;a href="https://pixabay.com/photos/astronomical-clock-prague-226897/"&gt;Falco&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This blog post is part of the 2021 &lt;a href="https://csadvent.christmas/"&gt;C# Advent Calendar&lt;/a&gt;. Go check out the other 49 great posts after you read mine, of course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;.NET 6 introduced two new types that many developers have been eagerly awaiting; &lt;code&gt;DateOnly&lt;/code&gt; and &lt;code&gt;TimeOnly&lt;/code&gt;. Both represent Date and Time separately; instead of relying on the &lt;code&gt;DateTime&lt;/code&gt; object, they're also Structs. This is great because sometimes, we, as developers, don't care about one of these types. Some object we've created might only care about the date and have no use for time, which could be significant as &lt;code&gt;DateOnly&lt;/code&gt; can now match the SQL Server &lt;code&gt;date&lt;/code&gt; type. Wouldn't it be great not to have to parse that the time out?&lt;/p&gt;

&lt;p&gt;I'm excited to use this is in my personal communications service that I run locally. I really should make a blog post about it; it essentially handles emails and texts for any of my local services or applications. Often, I just don't care about the date or time. I want something to go out every day at 8 A.M., like a status report, or go out at midnight on the first day of the month.&lt;/p&gt;

&lt;p&gt;Some things were changed for this example, but here's what the old &lt;code&gt;Message&lt;/code&gt; class looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageOldWay&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;DateAndTime&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In C# 9, we'd have to use &lt;code&gt;DateTime&lt;/code&gt; regardless of which method was called, which meant breaking things up. In the below example, we don't care about the time; we just need to know the content of the message and what the date is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messageOldWay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageOldWay&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Something Important!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateAndTime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;SendMessageOldWay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messageOldWay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SendMessageOldWay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MessageOldWay&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateAndTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToShortDateString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Message: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; \nDate: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not terribly complicated, but it is annoying to deal with unneeded code.&lt;/p&gt;

&lt;p&gt;Here's what the new message class looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Message&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;!;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateOnly&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Deconstruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;DateOnly&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've added a &lt;code&gt;Deconstruct&lt;/code&gt; in the new class to take advantage of .NET 6's improvements on deconstructing syntax; it makes unpacking things a bit easier. Usually, you'd want to use &lt;code&gt;Linq&lt;/code&gt; to handle collections, but today we're going to play with some more .NET 6 goodness.&lt;/p&gt;

&lt;p&gt;Now everything is a whole lot simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Don't forget to take a walk!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;SendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Message: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; \nDate: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we wanted to use a new method with just the time, we could make that, but we're going inherit from &lt;code&gt;Message&lt;/code&gt; and use both!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageWithTime&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;TimeOnly&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Deconstruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;DateOnly&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;TimeOnly&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that the new class has a &lt;code&gt;Deconstruct&lt;/code&gt; we can do something like this!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Start your work day"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Coffee time!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Take a short walk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Did you feed the cats?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Don't forget to eat lunch!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Drink Water!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Drink MORE Water"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Go for a walk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"I don't know what to say"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Work is over for the day!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Eat Dinner!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;SendMessages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SendMessages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MessageWithTime&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;postionInQue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"You're place in Que is: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;postionInQue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; \nMessage: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; \nDate: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; \nTime: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;\n"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to the pre-existing &lt;code&gt;Deconstruct&lt;/code&gt; in &lt;code&gt;Dictionaries&lt;/code&gt;, we can unpack the Key/Value Pair in our foreach statement, making it more readable. One of the great things is that many .NET types come with &lt;code&gt;Deconstruct&lt;/code&gt; built-in!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;foreach (var (postionInQue, message) in messages)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Before this, we'd have to do something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"You're place in Que is: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; \nMessage: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; \nDate: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; \nTime: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;\n"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we built a &lt;code&gt;Deconstruct&lt;/code&gt; into our class, we're able to unpack everything in one line!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(var text, var date, var time) = message;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I hope you'll take advantage of the new &lt;code&gt;DateOnly&lt;/code&gt; and &lt;code&gt;TimeOnly&lt;/code&gt; data types. This example may be simplistic, but I really expect these two new types to change how systems are designed.&lt;/p&gt;

&lt;p&gt;How about you? Are you planning on taking advantage of these new types? What has you excited about them? Have you started adding deconstructs to your codebase? Do you even like &lt;code&gt;Deconstructs&lt;/code&gt;? Why or why not?&lt;/p&gt;

&lt;p&gt;Seriously, I really want to know what you think. Drop a comment below!&lt;/p&gt;

&lt;p&gt;Stay safe and hydrated.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>My Goals and Systems for 2021</title>
      <dc:creator>Christopher C. Johnson</dc:creator>
      <pubDate>Tue, 09 Mar 2021 13:00:00 +0000</pubDate>
      <link>https://forem.com/programazing/my-goals-and-systems-for-2021-23m2</link>
      <guid>https://forem.com/programazing/my-goals-and-systems-for-2021-23m2</guid>
      <description>&lt;p&gt;&lt;em&gt;Image by &lt;a href="https://www.pexels.com/photo/person-holding-white-ceramci-be-happy-painted-mug-851213/"&gt;Lisa Fotios&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Oh, look, another blog post about me. I know, I know, most of the posts lately have been about me and not much else. Don't worry that's changing this month.&lt;/p&gt;

&lt;p&gt;Like I mentioned in my &lt;a href="https://dev.to/moving-forward-into-2021"&gt;last blog post&lt;/a&gt; I'm committing to two blog posts a week. Sadly, this counts as the second post this week while I iron some things out for work.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"You do not rise to the level of your goals. You fall to the level of your systems." - &lt;a href="https://jamesclear.com"&gt;James Clear&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a powerful statement. So powerful in fact that I had it &lt;a href="https://twitter.com/Programazing/status/1352679173278621702?s=20"&gt;printed and framed&lt;/a&gt; so I could be reminded of that every day.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are my Goals?
&lt;/h2&gt;

&lt;p&gt;Unlike previous years I'm going to keep things simple&lt;/p&gt;

&lt;h3&gt;
  
  
  Focus on my health
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Diet&lt;/li&gt;
&lt;li&gt;Exercise&lt;/li&gt;
&lt;li&gt;Mental Health&lt;/li&gt;
&lt;li&gt;Daily Routines&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Focus on my career change
&lt;/h3&gt;

&lt;p&gt;I'm moving from being just a developer to also being a developer advocate, and an educator&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing&lt;/li&gt;
&lt;li&gt;Public Speaking&lt;/li&gt;
&lt;li&gt;Recording content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's only two areas of my life and look at how many things are involved. No wonder I only averaged a 70% success rate in previous years with my gigantic lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are my Systems?
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Health
&lt;/h2&gt;

&lt;p&gt;Luckily I already have some systems in place for these. Unlike previous years I didn’t wait until New Years' to get started. Back in October of 2020, I enlisted the help of a nutrition specialist and mental health professional to get my life in order. That’s also when I started minimizing my home which has been fantastic for my mental and physical wellbeing.&lt;/p&gt;

&lt;p&gt;Just a quick side-note, I track almost everything in  &lt;a href="https://www.myfitnesspal.com"&gt;MyFitnessPal&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Diet
&lt;/h4&gt;

&lt;p&gt;Without getting into specifics of the diet, I currently plan my meals two weeks in advance. That way I can figure out the ingredients needed and set up an &lt;a href="https://www.instacart.com/"&gt;Instacart&lt;/a&gt; delivery for the weekend. I usually spend Sunday prepping as much as I can and cooking for at least half the week.&lt;/p&gt;

&lt;p&gt;I try to stick to the same 20 or 30 recipes so I have variety but don't have to think too much about what I'm going to make that week.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exercise
&lt;/h4&gt;

&lt;p&gt;Exercise is built into my day now, whether I like it or not. I wake up at 5:30 A.M., do my planned exercises for at least 20-minutes, then head out on a morning walk. I walk three times a day; morning, afternoon, and evening. My walks are more of a time to think about the day or whatever’s on my mind.&lt;/p&gt;

&lt;p&gt;Eventually, in the late Spring, I’ll start hiking again.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mental Health
&lt;/h4&gt;

&lt;p&gt;Get a therapist. Why? Because we all have crap we're dealing with and it helps to talk to someone who understands how to frame things and help us understand them. I see my therapist virtually every two weeks and it's one of the best investments I've ever made. If you're in I.T. you're probably stressed, don't bottle it up.&lt;/p&gt;

&lt;h4&gt;
  
  
  Daily Routines
&lt;/h4&gt;

&lt;p&gt;I made this a section onto itself because I have daily routines that tie into everything I do, so it’s easier to think of it as a standalone category.&lt;br&gt;
After I get back from my walks I usually sit down with something to drink, that changes depending on the time of day, and write in my journal.&lt;/p&gt;

&lt;p&gt;Yeah, yeah, I can hear you now. “Oh, they keep a diary, how precious.” Well, maybe not you, but that's paraphrased from a few people.&lt;/p&gt;

&lt;p&gt;I find that physically writing in a journal, away from computers or smart devices, helps me think more fluidly. When I’m free of distractions ideas and thoughts seem to spring from nowhere and I capture them effortlessly. I’ve tried to do the same with note-taking apps but it’s just not the same.&lt;/p&gt;

&lt;p&gt;I’m still figuring out these daily routines so we’ll see what I come up with in the next quarterly review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Career
&lt;/h2&gt;

&lt;p&gt;Honestly, I don’t know what systems I’ll put in place around these new career changes. At the moment all I can do is use &lt;a href="https://todoist.com/productivity-methods/time-blocking"&gt;time blocking&lt;/a&gt; to study what others have done and practice my style.&lt;/p&gt;




&lt;p&gt;I tried to keep things short this time. I plan on focusing more intently on fewer things this year to have a higher chance of both success and excellence in what I choose to do. I hope you do the same.&lt;/p&gt;

&lt;p&gt;How are your goals coming along? Tell me all about it in the comments or send me a tweet. I want to hear from you.&lt;/p&gt;

&lt;p&gt;Stay safe and hydrate.&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
  </channel>
</rss>
