<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-1074964965522467583</atom:id><lastBuildDate>Wed, 08 Jul 2026 15:04:38 +0000</lastBuildDate><category>Trending</category><category>PWD Working</category><category>Roads</category><category>Software</category><category>Bridge</category><category>Building</category><category>Design calculations</category><category>Construction Procedure</category><category>Drawings</category><category>Estimate Preparation</category><category>Earth retaining structures</category><category>Programming</category><category>Tender</category><category>Survey</category><category>Formulas</category><category>Guidelines Books Type plan GR&#39;s Circulars</category><category>Structural Analysis</category><category>RTI</category><category>SSR</category><title>Useful for Civil Engineers of P.W.D. , Yogendra Borse</title><description>Day to Day working Calculations and Procedures and Methods in Public Works Department, Problems and Their solutions via Discussions or from Theory books.</description><link>https://www.yogipwd.com/</link><managingEditor>noreply@blogger.com (Yogendra)</managingEditor><generator>Blogger</generator><openSearch:totalResults>369</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-41306259701348704</guid><pubDate>Wed, 08 Jul 2026 14:59:36 +0000</pubDate><atom:updated>2026-07-08T20:34:38.637+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Design calculations</category><category domain="http://www.blogger.com/atom/ns#">Drawings</category><category domain="http://www.blogger.com/atom/ns#">Software</category><category domain="http://www.blogger.com/atom/ns#">Structural Analysis</category><title>R-Factor in Seismic Design</title><description>&lt;article&gt;
    &lt;header&gt;
        &lt;h1 style=&quot;color: #1a365d; font-family: &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; border-bottom: 2px solid #3182ce; padding-bottom: 10px;&quot;&gt;
            Why the Code &quot;Rewards&quot; Ductility: Mastering the R-Factor in Seismic Design (IS 1893 vs. IS 13920)
        &lt;/h1&gt;
        &lt;p style=&quot;font-style: italic; color: #4a5568; font-size: 1.1em; margin-top: 5px;&quot;&gt;
            Just for information only, an expert advice shall be taken case by case.
        &lt;/p&gt;
    &lt;/header&gt;

    &lt;hr style=&quot;border: 0; border-top: 1px solid #e2e8f0; margin: 20px 0;&quot; /&gt;

    &lt;section&gt;
        &lt;p&gt;
            As structural engineers, we often look at seismic design codes as a rigid set of rules. But if you look closer, building codes are actually giving you a massive design discount—&lt;strong&gt;if you know how to earn it&lt;/strong&gt;. 
        &lt;/p&gt;
        &lt;p&gt;
            Modern seismic codes (like India&#39;s &lt;strong&gt;IS 1893 (Part 1): 2016&lt;/strong&gt;) don’t scale down lateral forces because a building is inherently &quot;safe enough.&quot; They do it because they expect the structure to &lt;strong&gt;deform inelastically, dissipate seismic energy, and avoid catastrophic, brittle failure&lt;/strong&gt; through meticulous ductile detailing. 
        &lt;/p&gt;
        &lt;p&gt;
            The core philosophy is remarkably simple: 
            &lt;code style=&quot;background-color: #edf2f7; padding: 2px 6px; border-radius: 4px; font-weight: bold; color: #2b6cb0;&quot;&gt;
                More Confinement &amp;rarr; High Ductility &amp;rarr; Higher R-Value &amp;rarr; Lower Design Seismic Forces
            &lt;/code&gt;
        &lt;/p&gt;
    &lt;/section&gt;

    &lt;h2 style=&quot;color: #2c5282; margin-top: 30px;&quot;&gt;The Engineering Math: Design Base Shear vs. Elastic Demand&lt;/h2&gt;
    &lt;section&gt;
        &lt;p&gt;
            If we designed a structure to remain completely elastic during a severe earthquake, the building components would become impossibly massive, expensive, and impractical. Instead, codes allow us to divide the theoretical elastic base shear force by a &lt;strong&gt;Response Reduction Factor ($R$)&lt;/strong&gt;.
        &lt;/p&gt;
        
        &lt;div style=&quot;background-color: #f7fafc; border-left: 4px solid #3182ce; padding: 15px; margin: 20px 0; font-family: monospace; font-size: 1.2em; text-align: center;&quot;&gt;
            $$V_{design} = \frac{V_{elastic}}{R}$$
        &lt;/div&gt;

        &lt;p&gt;
            The value of $R$ directly depends on the seismic force-resisting system you choose and its level of detailing. A higher $R$ value directly drops your design lateral loads.
        &lt;/p&gt;
    &lt;/section&gt;

    &lt;h2 style=&quot;color: #2c5282; margin-top: 30px;&quot;&gt;Indian Code Equivalents: OMRF vs. SMRF&lt;/h2&gt;
    &lt;section&gt;
        &lt;p&gt;
            Just as international codes (ASCE 7) differentiate between Ordinary, Intermediate, and Special Moment Frames, the Indian Standard &lt;strong&gt;IS 1893 (Part 1): 2016 (Table 9)&lt;/strong&gt; rewards structural ductilty similarly:
        &lt;/p&gt;

        &lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0; font-family: Arial, sans-serif;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background-color: #2b6cb0; color: white; text-align: left;&quot;&gt;
                    &lt;th style=&quot;padding: 12px; border: 1px solid #cbd5e0;&quot;&gt;Frame Type&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px; border: 1px solid #cbd5e0;&quot;&gt;R-Factor (IS 1893)&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px; border: 1px solid #cbd5e0;&quot;&gt;Force Reduction&lt;/th&gt;
                    &lt;th style=&quot;padding: 12px; border: 1px solid #cbd5e0;&quot;&gt;Detailing Standard&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr style=&quot;background-color: #f7fafc;&quot;&gt;
                    &lt;td style=&quot;padding: 12px; border: 1px solid #cbd5e0; font-weight: bold;&quot;&gt;Ordinary Moment Resisting Frame (OMRF)&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px; border: 1px solid #cbd5e0; text-align: center;&quot;&gt;&lt;strong&gt;3.0&lt;/strong&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px; border: 1px solid #cbd5e0; color: #718096;&quot;&gt;Baseline forces&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px; border: 1px solid #cbd5e0;&quot;&gt;IS 456 (Normal RC detailing)&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr style=&quot;background-color: #ffffff;&quot;&gt;
                    &lt;td style=&quot;padding: 12px; border: 1px solid #cbd5e0; font-weight: bold; color: #2b6cb0;&quot;&gt;Special Moment Resisting Frame (SMRF)&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px; border: 1px solid #cbd5e0; text-align: center; color: #2b6cb0;&quot;&gt;&lt;strong&gt;5.0&lt;/strong&gt;&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px; border: 1px solid #cbd5e0; font-weight: bold; color: #2f855a;&quot;&gt;~40% Load Reduction&lt;/td&gt;
                    &lt;td style=&quot;padding: 12px; border: 1px solid #cbd5e0; font-weight: bold;&quot;&gt;IS 13920: 2016 (Ductile detailing)&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;

        &lt;p&gt;
            By opting for an &lt;strong&gt;SMRF&lt;/strong&gt; instead of an OMRF, the code allows you to reduce your structural design seismic forces by &lt;strong&gt;40%&lt;/strong&gt;. However, this &quot;discount&quot; comes with a strict contractual obligation: you must enforce stringent detailing requirements on site.
        &lt;/p&gt;
    &lt;/section&gt;

    &lt;h2 style=&quot;color: #2c5282; margin-top: 30px;&quot;&gt;How Confinement Changes the Game (IS 13920 Requirements)&lt;/h2&gt;
    &lt;section&gt;
        &lt;p&gt;
            What does an $R = 5.0$ demand on the blueprint? It requires changing the failure mode from brittle concrete crushing to ductile steel yielding. This is achieved by confining the concrete core using closely spaced links (ties/stirrups).
        &lt;/p&gt;
        
        &lt;p&gt;According to &lt;strong&gt;IS 13920: 2016&lt;/strong&gt;, as we transition into ductile zones (such as plastic hinge regions at beam-column junctions), the detailing requirements become incredibly demanding:&lt;/p&gt;

        &lt;ul style=&quot;line-height: 1.6; color: #2d3748;&quot;&gt;
            &lt;li&gt;&lt;strong&gt;Tighter Confinement:&lt;/strong&gt; Closely spaced links prevent the longitudinal reinforcement bars from buckling prematurely under cyclic axial compression.&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Closer Tie Spacing ($s_v$):&lt;/strong&gt; In the plastic hinge zone ($l_o$) of a column, the spacing of links is restricted to the minimum of $1/4$ of the minimum column dimension, 6 times the diameter of the smallest longitudinal bar, or $100\text{ mm}$ (Clause 8.1).&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Stronger Anchorage:&lt;/strong&gt; Beam longitudinal bars entering an external joint must be anchored with a $90^\circ$ bend plus an extension length of at least $8$ times the bar diameter, keeping the hook safely embedded in the confined column core.&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Controlled Splices:&lt;/strong&gt; Lap splices are strictly prohibited within the joint core or within a distance of $2d$ from the face of the beam or column connection where plastic hinges are expected to form.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/section&gt;

    &lt;hr style=&quot;border: 0; border-top: 1px solid #e2e8f0; margin: 30px 0;&quot; /&gt;

    &lt;section style=&quot;background-color: #ebf8ff; padding: 20px; border-radius: 8px; border: 1px solid #bee3f8;&quot;&gt;
        &lt;h3 style=&quot;color: #2b6cb0; margin-top: 0;&quot;&gt;Takeaway&lt;/h3&gt;
        &lt;p style=&quot;margin-bottom: 0;&quot;&gt;
            Next time you select your Response Reduction Factor ($R$) in your structural analysis software, remember that it is not just a numerical setting. An $R$-value is a direct reflection of the physical confinement you provide on-site. If your site drawings do not rigorously enforce the dense, intricate tie spacings specified by &lt;strong&gt;IS 13920&lt;/strong&gt;, your structure will not possess the ductility assumed in your calculations—putting it at risk during a design-level seismic event. Design responsibly!
        &lt;/p&gt;
    &lt;/section&gt;
&lt;/article&gt;
&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/07/r-factor-in-seismic-design.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-7104515336099915086</guid><pubDate>Tue, 07 Jul 2026 05:39:14 +0000</pubDate><atom:updated>2026-07-07T11:15:13.783+05:30</atom:updated><title>Steel Structures Design checks calculator tool</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Steel Structures Design Toolkit (Offline)&lt;/title&gt;
    &lt;style&gt;
        /* Modern Dark Theme - CSS Core */
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        body {
            background-color: #111827;
            color: #f3f4f6;
            font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif;
            padding: 24px;
            line-height: 1.5;
        }
        .container {
            max-width: 1000px;
            margin: 0 auto;
        }
        header {
            text-align: center;
            border-bottom: 1px solid #374151;
            padding-bottom: 16px;
            margin-bottom: 32px;
        }
        h1 {
            color: #60a5fa;
            font-size: 1.8rem;
            letter-spacing: 0.05em;
        }
        p.subtitle {
            color: #9ca3af;
            font-size: 0.875rem;
            margin-top: 4px;
        }
        
        /* Grid Layout */
        .grid {
            display: grid;
            grid-template-columns: 1fr;
            gap: 24px;
        }
        @media (min-width: 768px) {
            .grid {
                grid-template-columns: 1fr 1fr;
            }
            .col-span-2 {
                grid-column: span 2;
            }
            .triple-grid {
                display: grid;
                grid-template-columns: 1fr 1fr 1fr;
                gap: 16px;
            }
        }

        /* Card Styles */
        .card {
            background-color: #1f2937;
            border: 1px solid #374151;
            border-radius: 12px;
            padding: 24px;
            box-shadow: 0 4px 6px -1px rgba(0,0,0,0.3);
        }
        .card h2 {
            font-size: 1.25rem;
            margin-bottom: 16px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .text-blue { color: #60a5fa; }
        .text-emerald { color: #34d399; }
        .text-purple { color: #c084fc; }

        /* Form Controls */
        .form-group {
            margin-bottom: 16px;
        }
        .grid-2-col {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 8px;
        }
        label {
            display: block;
            font-size: 0.75rem;
            text-transform: uppercase;
            letter-spacing: 0.05em;
            color: #9ca3af;
            margin-bottom: 4px;
            font-weight: 500;
        }
        input {
            width: 100%;
            background-color: #374151;
            border: 1px solid #4b5563;
            color: #ffffff;
            border-radius: 6px;
            padding: 8px 12px;
            font-size: 1rem;
            outline: none;
        }
        input:focus {
            border-color: #60a5fa;
        }

        /* Buttons */
        button {
            width: 100%;
            color: white;
            font-weight: 500;
            padding: 10px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 1rem;
            transition: background 0.2s;
            margin-top: 8px;
        }
        .btn-blue { background-color: #2563eb; }
        .btn-blue:hover { background-color: #1d4ed8; }
        .btn-emerald { background-color: #059669; }
        .btn-emerald:hover { background-color: #047857; }
        .btn-purple { background-color: #9333ea; }
        .btn-purple:hover { background-color: #7e22ce; }

        /* Results Display */
        .result-box {
            margin-top: 16px;
            padding: 12px;
            background-color: #111827;
            border-radius: 6px;
        }
        .border-blue { border-left: 4px solid #2563eb; }
        .border-emerald { border-left: 4px solid #059669; }
        
        .result-title {
            font-size: 0.75rem;
            text-transform: uppercase;
            color: #9ca3af;
            display: block;
        }
        .result-value {
            font-size: 1.5rem;
            font-weight: bold;
            margin-top: 4px;
        }
        
        /* Connection Specific Outputs */
        .conn-outputs {
            margin-top: 24px;
            border-top: 1px solid #374151;
            padding-top: 16px;
            display: grid;
            grid-template-columns: 1fr;
            gap: 16px;
        }
        @media (min-width: 640px) {
            .conn-outputs { grid-template-columns: 1fr 1fr 1fr; }
        }
        .box-highlight {
            border: 2px solid #a855f7;
            background-color: rgba(147, 51, 234, 0.1);
        }
        .text-purple-light { color: #d8b4fe; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

    &lt;div class=&quot;container&quot;&gt;
        &lt;header&gt;
            &lt;h1&gt;Steel Structures Design Toolkit&lt;/h1&gt;
            &lt;p class=&quot;subtitle&quot;&gt;Offline Mode • Based on IS 800:2007 (Limit State Design)&lt;/p&gt;
        &lt;/header&gt;

        &lt;div class=&quot;grid&quot;&gt;

            &lt;div class=&quot;card&quot;&gt;
                &lt;h2 class=&quot;text-blue&quot;&gt;&lt;span&gt;1.&lt;/span&gt; Tension Member Capacity&lt;/h2&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Gross Area, A&lt;sub&gt;g&lt;/sub&gt; (mm²)&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;tension-ag&quot; value=&quot;1200&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Yield Strength, f&lt;sub&gt;y&lt;/sub&gt; (MPa)&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;tension-fy&quot; value=&quot;250&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Partial Safety Factor, γ&lt;sub&gt;m0&lt;/sub&gt;&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;tension-gam&quot; value=&quot;1.10&quot; step=&quot;0.01&quot;&gt;
                &lt;/div&gt;
                &lt;button onclick=&quot;calculateTension()&quot; class=&quot;btn-blue&quot;&gt;Calculate Capacity&lt;/button&gt;
                
                &lt;div class=&quot;result-box border-blue&quot;&gt;
                    &lt;span class=&quot;result-title&quot;&gt;Design Strength, T&lt;sub&gt;d&lt;/sub&gt;&lt;/span&gt;
                    &lt;div id=&quot;tension-result&quot; class=&quot;result-value&quot;&gt;272.73 kN&lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

            &lt;div class=&quot;card&quot;&gt;
                &lt;h2 class=&quot;text-emerald&quot;&gt;&lt;span&gt;2.&lt;/span&gt; Compression &amp; Slenderness&lt;/h2&gt;
                &lt;div class=&quot;form-group grid-2-col&quot;&gt;
                    &lt;div&gt;
                        &lt;label&gt;Eff. Length, L&lt;sub&gt;e&lt;/sub&gt; (mm)&lt;/label&gt;
                        &lt;input type=&quot;number&quot; id=&quot;comp-le&quot; value=&quot;3000&quot;&gt;
                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;label&gt;Rad. of Gyration, r (mm)&lt;/label&gt;
                        &lt;input type=&quot;number&quot; id=&quot;comp-r&quot; value=&quot;25&quot;&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Young&#39;s Modulus, E (GPa)&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;comp-e&quot; value=&quot;200&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Moment of Inertia, I (×10⁴ mm⁴)&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;comp-i&quot; value=&quot;75&quot;&gt;
                &lt;/div&gt;
                &lt;button onclick=&quot;calculateCompression()&quot; class=&quot;btn-emerald&quot;&gt;Calculate Buckling&lt;/button&gt;
                
                &lt;div class=&quot;result-box border-emerald grid-2-col&quot; style=&quot;padding: 12px;&quot;&gt;
                    &lt;div&gt;
                        &lt;span class=&quot;result-title&quot;&gt;Slenderness, λ&lt;/span&gt;
                        &lt;div id=&quot;comp-lambda-res&quot; class=&quot;result-value&quot; style=&quot;font-size: 1.25rem;&quot;&gt;120.00&lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;span class=&quot;result-title&quot;&gt;Euler Load, P&lt;sub&gt;cr&lt;/sub&gt;&lt;/span&gt;
                        &lt;div id=&quot;comp-pcr-res&quot; class=&quot;result-value&quot; style=&quot;font-size: 1.25rem;&quot;&gt;164.49 kN&lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

            &lt;div class=&quot;card col-span-2&quot;&gt;
                &lt;h2 class=&quot;text-purple&quot;&gt;&lt;span&gt;3.&lt;/span&gt; Bolt Connection Strength (Shear &amp; Bearing)&lt;/h2&gt;
                &lt;div class=&quot;triple-grid&quot;&gt;
                    &lt;div&gt;
                        &lt;div class=&quot;form-group&quot;&gt;
                            &lt;label&gt;Bolt Ultimate Strength, f&lt;sub&gt;ub&lt;/sub&gt; (MPa)&lt;/label&gt;
                            &lt;input type=&quot;number&quot; id=&quot;bolt-fub&quot; value=&quot;400&quot;&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;form-group&quot;&gt;
                            &lt;label&gt;Net Area of Bolt, A&lt;sub&gt;b&lt;/sub&gt; (mm²)&lt;/label&gt;
                            &lt;input type=&quot;number&quot; id=&quot;bolt-ab&quot; value=&quot;245&quot;&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div&gt;
                        &lt;div class=&quot;form-group&quot;&gt;
                            &lt;label&gt;Plate Ultimate Strength, f&lt;sub&gt;u&lt;/sub&gt; (MPa)&lt;/label&gt;
                            &lt;input type=&quot;number&quot; id=&quot;bolt-fu&quot; value=&quot;410&quot;&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;form-group grid-2-col&quot;&gt;
                            &lt;div&gt;
                                &lt;label&gt;Dia, d (mm)&lt;/label&gt;
                                &lt;input type=&quot;number&quot; id=&quot;bolt-d&quot; value=&quot;20&quot;&gt;
                            &lt;/div&gt;
                            &lt;div&gt;
                                &lt;label&gt;Plate t (mm)&lt;/label&gt;
                                &lt;input type=&quot;number&quot; id=&quot;bolt-t&quot; value=&quot;12&quot;&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div style=&quot;display: flex; flex-direction: column; justify-content: space-between;&quot;&gt;
                        &lt;div class=&quot;form-group&quot;&gt;
                            &lt;label&gt;Bearing Factor, k&lt;sub&gt;b&lt;/sub&gt;&lt;/label&gt;
                            &lt;input type=&quot;number&quot; id=&quot;bolt-kb&quot; value=&quot;0.5&quot; step=&quot;0.05&quot;&gt;
                        &lt;/div&gt;
                        &lt;button onclick=&quot;calculateBolt()&quot; class=&quot;btn-purple&quot;&gt;Evaluate Connection&lt;/button&gt;
                    &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class=&quot;conn-outputs&quot;&gt;
                    &lt;div class=&quot;result-box&quot; style=&quot;border: 1px solid #374151;&quot;&gt;
                        &lt;span class=&quot;result-title&quot;&gt;Bolt Shear, V&lt;sub&gt;dsb&lt;/sub&gt;&lt;/span&gt;
                        &lt;div id=&quot;bolt-vdsb&quot; class=&quot;result-value&quot; style=&quot;font-size: 1.25rem;&quot;&gt;45.26 kN&lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;result-box&quot; style=&quot;border: 1px solid #374151;&quot;&gt;
                        &lt;span class=&quot;result-title&quot;&gt;Bolt Bearing, V&lt;sub&gt;dpb&lt;/sub&gt;&lt;/span&gt;
                        &lt;div id=&quot;bolt-vdpb&quot; class=&quot;result-value&quot; style=&quot;font-size: 1.25rem; color: #fbbf24;&quot;&gt;78.72 kN&lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;result-box box-highlight&quot;&gt;
                        &lt;span class=&quot;result-title&quot; style=&quot;color: #c084fc; font-weight: bold;&quot;&gt;Governing Value&lt;/span&gt;
                        &lt;div id=&quot;bolt-governing&quot; class=&quot;result-value&quot; style=&quot;font-size: 1.4rem; color: #e9d5ff;&quot;&gt;45.26 kN&lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

        &lt;/div&gt;
    &lt;/div&gt;

    &lt;script&gt;
        function calculateTension() {
            const ag = parseFloat(document.getElementById(&#39;tension-ag&#39;).value) || 0;
            const fy = parseFloat(document.getElementById(&#39;tension-fy&#39;).value) || 0;
            const gam = parseFloat(document.getElementById(&#39;tension-gam&#39;).value) || 1.1;

            const td = (ag * fy) / gam / 1000;
            document.getElementById(&#39;tension-result&#39;).innerText = td.toFixed(2) + &#39; kN&#39;;
        }

        function calculateCompression() {
            const le = parseFloat(document.getElementById(&#39;comp-le&#39;).value) || 0;
            const r = parseFloat(document.getElementById(&#39;comp-r&#39;).value) || 1;
            const eGPa = parseFloat(document.getElementById(&#39;comp-e&#39;).value) || 200;
            const iSc = parseFloat(document.getElementById(&#39;comp-i&#39;).value) || 0;

            const lambda = le / r;
            const E_MPa = eGPa * 1000;
            const I_mm4 = iSc * 10000; 

            const pcr = (Math.PI * Math.PI * E_MPa * I_mm4) / (le * le) / 1000; 

            document.getElementById(&#39;comp-lambda-res&#39;).innerText = lambda.toFixed(2);
            document.getElementById(&#39;comp-pcr-res&#39;).innerText = pcr.toFixed(2) + &#39; kN&#39;;
        }

        function calculateBolt() {
            const fub = parseFloat(document.getElementById(&#39;bolt-fub&#39;).value) || 0;
            const ab = parseFloat(document.getElementById(&#39;bolt-ab&#39;).value) || 0;
            const fu = parseFloat(document.getElementById(&#39;bolt-fu&#39;).value) || 0;
            const d = parseFloat(document.getElementById(&#39;bolt-d&#39;).value) || 0;
            const t = parseFloat(document.getElementById(&#39;bolt-t&#39;).value) || 0;
            const kb = parseFloat(document.getElementById(&#39;bolt-kb&#39;).value) || 0;
            const gam = 1.25; 

            const vdsb = (fub * ab) / (Math.sqrt(3) * gam) / 1000;
            const vdpb = (2.5 * kb * d * t * fu) / gam / 1000;
            const governing = Math.min(vdsb, vdpb);

            document.getElementById(&#39;bolt-vdsb&#39;).innerText = vdsb.toFixed(2) + &#39; kN&#39;;
            document.getElementById(&#39;bolt-vdpb&#39;).innerText = vdpb.toFixed(2) + &#39; kN&#39;;
            document.getElementById(&#39;bolt-governing&#39;).innerText = governing.toFixed(2) + &#39; kN&#39;;
        }
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/07/steel-structures-design-checks.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-3410337850703798666</guid><pubDate>Fri, 26 Jun 2026 10:36:25 +0000</pubDate><atom:updated>2026-07-04T08:44:46.252+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Software</category><title>complex to simple KML</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;AutoCAD KML Element Extractor&lt;/title&gt;
    &lt;style&gt;
        body {
            font-family: &#39;Segoe UI&#39;, Tahoma, Geneva, Verdana, sans-serif;
            margin: 30px;
            background-color: #f8f9fa;
            color: #333;
        }
        .container {
            max-width: 750px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.08);
        }
        h2 { color: #2c3e50; margin-top: 0; border-bottom: 2px solid #ecf0f1; padding-bottom: 10px; }
        p { color: #7f8c8d; font-size: 0.95em; line-height: 1.5; }
        .drop-zone {
            margin: 25px 0;
            padding: 30px;
            border: 3px dashed #3498db;
            border-radius: 6px;
            background: #eaf2f8;
            text-align: center;
            cursor: pointer;
            transition: background 0.3s;
        }
        .drop-zone:hover, .drop-zone.dragover { background: #d4e6f1; }
        .btn {
            display: inline-block;
            background-color: #2ecc71;
            color: white;
            padding: 12px 24px;
            border: none;
            border-radius: 4px;
            font-weight: bold;
            font-size: 1em;
            cursor: pointer;
            text-decoration: none;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
        .btn:hover { background-color: #27ae60; }
        .btn:disabled { background-color: #bdc3c7; cursor: not-allowed; box-shadow: none; }
        .status-box {
            margin: 20px 0;
            padding: 15px;
            border-radius: 4px;
            display: none;
            font-weight: 500;
        }
        .info { background-color: #e8f4fd; color: #2980b9; border-left: 5px solid #2980b9; }
        .success { background-color: #e8f8f5; color: #27ae60; border-left: 5px solid #27ae60; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;container&quot;&gt;
    &lt;h2&gt;AutoCAD All Geometry Extractor (Lines &amp; Polygons)&lt;/h2&gt;
    &lt;p&gt;Extracts all linear assets, right-of-way lines, site boundaries, and closed polygons out of messy AutoCAD KML layers and converts them into cleanly structured, GIS-ready entities.&lt;/p&gt;
    
    &lt;div class=&quot;drop-zone&quot; id=&quot;dropZone&quot; onclick=&quot;document.getElementById(&#39;fileInput&#39;).click()&quot;&gt;
        &lt;strong&gt;Click to select or drag your complex CAD KML here&lt;/strong&gt;
        &lt;input type=&quot;file&quot; id=&quot;fileInput&quot; accept=&quot;.kml&quot; style=&quot;display: none;&quot; /&gt;
    &lt;/div&gt;

    &lt;div id=&quot;status&quot; class=&quot;status-box info&quot;&gt;&lt;/div&gt;
    
    &lt;div style=&quot;text-align: center; margin-top: 25px;&quot;&gt;
        &lt;button id=&quot;downloadBtn&quot; class=&quot;btn&quot; disabled&gt;Download Flattened KML&lt;/button&gt;
    &lt;/div&gt;
&lt;/div&gt;
  
  &lt;div style=&quot;font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe UI&#39;, Roboto, Helvetica, Arial, sans-serif; color: #333; line-height: 1.6; max-width: 800px; margin: 0 auto; padding: 20px;&quot;&gt;
    
    &lt;h1 style=&quot;color: #1a73e8; border-bottom: 2px solid #e8f0fe; padding-bottom: 10px;&quot;&gt;User Guide: KML Geometry Extractor &amp;amp; Flattener&lt;/h1&gt;
    
    &lt;p style=&quot;font-size: 16px; color: #5f6368;&quot;&gt;
        Welcome to the user manual for the &lt;strong&gt;KML Geometry Extractor Tool&lt;/strong&gt;. This lightweight, browser-based tool allows you to isolate, clean, and flatten spatial geometry vectors directly from any standard &lt;code&gt;.kml&lt;/code&gt; file. 
    &lt;/p&gt;

    &lt;hr style=&quot;border: 0; border-top: 1px solid #e0e0e0; margin: 25px 0;&quot; /&gt;

    &lt;h2 style=&quot;color: #202124; font-size: 20px;&quot;&gt;What This Tool Does&lt;/h2&gt;
    &lt;p&gt;Complex KML files generated from GIS software or Google Earth often contain deeply nested folders, complex metadata tables, and erratic styling. This tool scripts away that clutter by:&lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px; color: #3c4043;&quot;&gt;
        &lt;li style=&quot;margin-bottom: 8px;&quot;&gt;&lt;strong&gt;Extracting Geometries:&lt;/strong&gt; Automatically scans files to pull out all &lt;code&gt;LineString&lt;/code&gt; (paths) and &lt;code&gt;Polygon&lt;/code&gt; elements.&lt;/li&gt;
        &lt;li style=&quot;margin-bottom: 8px;&quot;&gt;&lt;strong&gt;Data Cleaning:&lt;/strong&gt; Scrubs out whitespaces and faulty formatting to standardize coordinates.&lt;/li&gt;
        &lt;li style=&quot;margin-bottom: 8px;&quot;&gt;&lt;strong&gt;Flattening Hierarchies:&lt;/strong&gt; Strips down multi-nested structures into a fast-loading, simplified KML tree.&lt;/li&gt;
        &lt;li style=&quot;margin-bottom: 8px;&quot;&gt;&lt;strong&gt;Applying Clean Styles:&lt;/strong&gt; Assigns visible red styles to lines and semi-transparent green styles to polygons automatically.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;hr style=&quot;border: 0; border-top: 1px solid #e0e0e0; margin: 25px 0;&quot; /&gt;

    &lt;h2 style=&quot;color: #202124; font-size: 20px;&quot;&gt;How to Use the Tool&lt;/h2&gt;
    
    &lt;div style=&quot;background-color: #f8f9fa; border-left: 4px solid #1a73e8; padding: 15px; margin-bottom: 20px; border-radius: 4px;&quot;&gt;
        &lt;p style=&quot;margin: 0; font-weight: bold; color: #1a73e8;&quot;&gt;Step 1: Upload Your KML File&lt;/p&gt;
        &lt;p style=&quot;margin: 5px 0 0 0; color: #5f6368;&quot;&gt;You can click the &lt;strong&gt;Choose File / Browse&lt;/strong&gt; input button to select your file, or simply drag and drop your target &lt;code&gt;.kml&lt;/code&gt; file directly into the designated drop zone area on your screen.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background-color: #f8f9fa; border-left: 4px solid #1a73e8; padding: 15px; margin-bottom: 20px; border-radius: 4px;&quot;&gt;
        &lt;p style=&quot;margin: 0; font-weight: bold; color: #1a73e8;&quot;&gt;Step 2: Monitor Real-Time Status&lt;/p&gt;
        &lt;p style=&quot;margin: 5px 0 0 0; color: #5f6368;&quot;&gt;Watch the status display box. The script processes calculations instantly in your browser cache. Upon completion, it will output a success notification showing exactly how many lines and polygons were successfully parsed.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background-color: #f8f9fa; border-left: 4px solid #1a73e8; padding: 15px; margin-bottom: 20px; border-radius: 4px;&quot;&gt;
        &lt;p style=&quot;margin: 0; font-weight: bold; color: #1a73e8;&quot;&gt;Step 3: Download the Optimized File&lt;/p&gt;
        &lt;p style=&quot;margin: 5px 0 0 0; color: #5f6368;&quot;&gt;The &lt;strong&gt;Download Button&lt;/strong&gt; will unlock dynamically after processing completes. Click it to save your freshly optimized file. The export file will match your source file name appended with &lt;code&gt;_flat_all.kml&lt;/code&gt;.&lt;/p&gt;
    &lt;/div&gt;

    &lt;hr style=&quot;border: 0; border-top: 1px solid #e0e0e0; margin: 25px 0;&quot; /&gt;

    &lt;h2 style=&quot;color: #202124; font-size: 20px;&quot;&gt;Troubleshooting Errors&lt;/h2&gt;
    
    &lt;table style=&quot;width: 100%; border-collapse: collapse; margin-top: 15px; font-size: 14px;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background-color: #f1f3f4; border-bottom: 2px solid #dadce0; text-align: left;&quot;&gt;
                &lt;th style=&quot;padding: 10px; font-weight: 600; color: #202124;&quot;&gt;Error Notice&lt;/th&gt;
                &lt;th style=&quot;padding: 10px; font-weight: 600; color: #202124;&quot;&gt;Root Cause&lt;/th&gt;
                &lt;th style=&quot;padding: 10px; font-weight: 600; color: #202124;&quot;&gt;Resolution Path&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr style=&quot;border-bottom: 1px solid #e0e0e0;&quot;&gt;
                &lt;td style=&quot;padding: 10px; font-weight: bold; color: #d93025;&quot;&gt;&quot;No LineString or Polygon data found...&quot;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px; color: #5f6368;&quot;&gt;The uploaded file contains only points/placemarks or metadata tables with no actual path tracks or vector geometry lines.&lt;/td&gt;
                &lt;td style=&quot;padding: 10px; color: #5f6368;&quot;&gt;Verify that your spatial source contains lines or shapes before uploading.&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;border-bottom: 1px solid #e0e0e0;&quot;&gt;
                &lt;td style=&quot;padding: 10px; font-weight: bold; color: #d93025;&quot;&gt;&quot;Execution aborted: Corrupt xml layout...&quot;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px; color: #5f6368;&quot;&gt;The structural layout of your file breaks standard XML code parser rules or has corrupt tag nestings.&lt;/td&gt;
                &lt;td style=&quot;padding: 10px; color: #5f6368;&quot;&gt;Re-save or export the file out of your GIS program (like Google Earth) to rebuild its XML framework.&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;div style=&quot;margin-top: 30px; padding: 15px; background-color: #fff8e1; border: 1px solid #ffe082; border-radius: 4px;&quot;&gt;
        &lt;p style=&quot;margin: 0; font-size: 13px; color: #b78103;&quot;&gt;
            &lt;strong&gt;Privacy Note:&lt;/strong&gt; This application relies entirely on client-side JavaScript. Your spatial geographical files are parsed locally inside your machine&#39;s browser memory window. No spatial vector data or document layers are uploaded or sent to external servers.
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
let optimizedKMLContent = &quot;&quot;;
let originalFileName = &quot;extracted_geometries.kml&quot;;

const fileInput = document.getElementById(&#39;fileInput&#39;);
const dropZone = document.getElementById(&#39;dropZone&#39;);
const downloadBtn = document.getElementById(&#39;downloadBtn&#39;);

fileInput.addEventListener(&#39;change&#39;, (e) =&gt; handleFile(e.target.files[0]));

dropZone.addEventListener(&#39;dragover&#39;, (e) =&gt; { e.preventDefault(); dropZone.classList.add(&#39;dragover&#39;); });
dropZone.addEventListener(&#39;dragleave&#39;, () =&gt; dropZone.classList.remove(&#39;dragover&#39;));
dropZone.addEventListener(&#39;drop&#39;, (e) =&gt; {
    e.preventDefault();
    dropZone.classList.remove(&#39;dragover&#39;);
    if (e.dataTransfer.files.length &gt; 0) {
        fileInput.files = e.dataTransfer.files;
        handleFile(e.dataTransfer.files[0]);
    }
});

function parseCoordsText(text) {
    if (!text) return &quot;&quot;;
    let points = [];
    const pairs = text.trim().split(/[\s\n\r]+/);
    pairs.forEach(pair =&gt; {
        const parts = pair.split(&#39;,&#39;);
        if (parts.length &gt;= 2) {
            const lon = parts[0].trim();
            const lat = parts[1].trim();
            const alt = parts[2] ? parts[2].trim() : &quot;0&quot;;
            if (lon &amp;&amp; lat &amp;&amp; !isNaN(parseFloat(lon)) &amp;&amp; !isNaN(parseFloat(lat))) {
                points.push(`${lon},${lat},${alt}`);
            }
        }
    });
    return points.join(&#39;\n\t\t\t\t&#39;);
}

function handleFile(file) {
    if (!file) return;
    originalFileName = file.name.replace(&quot;.kml&quot;, &quot;_flat_all.kml&quot;);
    showStatus(&quot;Extracting line and polygon layers...&quot;, &quot;info&quot;);
    downloadBtn.disabled = true;

    const reader = new FileReader();
    reader.onload = function(evt) {
        try {
            const parser = new DOMParser();
            const xmlDoc = parser.parseFromString(evt.target.result, &quot;text/xml&quot;);
            
            let placemarksElements = xmlDoc.getElementsByTagName(&quot;Placemark&quot;);
            let kmlPlacemarksBlocks = [];
            let lineCount = 0;
            let polyCount = 0;

            for (let i = 0; i &lt; placemarksElements.length; i++) {
                const pm = placemarksElements[i];
                const nameTag = pm.getElementsByTagName(&quot;name&quot;)[0];
                const pmName = nameTag ? nameTag.textContent.trim() : `Feature_${i+1}`;
                
                // Look for internal geometries
                const lineStrings = pm.getElementsByTagName(&quot;LineString&quot;);
                const polygons = pm.getElementsByTagName(&quot;Polygon&quot;);

                // Process standard lines
                for (let j = 0; j &lt; lineStrings.length; j++) {
                    const coordTag = lineStrings[j].getElementsByTagName(&quot;coordinates&quot;)[0];
                    if (!coordTag) continue;
                    const cleanedCoords = parseCoordsText(coordTag.textContent);
                    if (!cleanedCoords) continue;

                    lineCount++;
                    kmlPlacemarksBlocks.push(`
        &lt;Placemark&gt;
          &lt;name&gt;${pmName} (Line ${lineCount})&lt;/name&gt;
          &lt;styleUrl&gt;#extractedLineStyle&lt;/styleUrl&gt;
          &lt;LineString&gt;
            &lt;tessellate&gt;1&lt;/tessellate&gt;
            &lt;altitudeMode&gt;clampToGround&lt;/altitudeMode&gt;
            &lt;coordinates&gt;
\t\t\t\t${cleanedCoords}
            &lt;/coordinates&gt;
          &lt;/LineString&gt;
        &lt;/Placemark&gt;`);
                }

                // Process Polygons
                for (let k = 0; k &lt; polygons.length; k++) {
                    const coordTag = polygons[k].getElementsByTagName(&quot;coordinates&quot;)[0]; // Target outer boundaries primarily
                    if (!coordTag) continue;
                    const cleanedCoords = parseCoordsText(coordTag.textContent);
                    if (!cleanedCoords) continue;

                    polyCount++;
                    kmlPlacemarksBlocks.push(`
        &lt;Placemark&gt;
          &lt;name&gt;${pmName} (Polygon ${polyCount})&lt;/name&gt;
          &lt;styleUrl&gt;#extractedPolyStyle&lt;/styleUrl&gt;
          &lt;Polygon&gt;
            &lt;tessellate&gt;1&lt;/tessellate&gt;
            &lt;altitudeMode&gt;clampToGround&lt;/altitudeMode&gt;
            &lt;outerBoundaryIs&gt;
              &lt;LinearRing&gt;
                &lt;coordinates&gt;
\t\t\t\t\t${cleanedCoords}
                &lt;/coordinates&gt;
              &lt;/LinearRing&gt;
            &lt;/outerBoundaryIs&gt;
          &lt;/Polygon&gt;
        &lt;/Placemark&gt;`);
                }
            }

            if (kmlPlacemarksBlocks.length === 0) {
                showStatus(&quot;Error: No LineString or Polygon data found in this file.&quot;, &quot;info&quot;);
                return;
            }

            // Assembly structure
            optimizedKMLContent = `&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;kml xmlns=&quot;http://www.opengis.net/kml/2.2&quot;&gt;
  &lt;Document&gt;
    &lt;name&gt;${file.name.replace(&quot;.kml&quot;, &quot; (Flattened Elements)&quot;)}&lt;/name&gt;
    &lt;Style id=&quot;extractedLineStyle&quot;&gt;
      &lt;LineStyle&gt;&lt;color&gt;ff0000ff&lt;/color&gt;&lt;width&gt;3&lt;/width&gt;&lt;/LineStyle&gt;
    &lt;/Style&gt;
    &lt;Style id=&quot;extractedPolyStyle&quot;&gt;
      &lt;LineStyle&gt;&lt;color&gt;ff00ff00&lt;/color&gt;&lt;width&gt;2&lt;/width&gt;&lt;/LineStyle&gt;
      &lt;PolyStyle&gt;&lt;color&gt;4000ff00&lt;/color&gt;&lt;fill&gt;1&lt;/fill&gt;&lt;outline&gt;1&lt;/outline&gt;&lt;/PolyStyle&gt;
    &lt;/Style&gt;
    ${kmlPlacemarksBlocks.join(&#39;\n&#39;)}
  &lt;/Document&gt;
&lt;/kml&gt;`;

            showStatus(`Success! Extracted ${lineCount} LineString(s) and ${polyCount} Polygon(s). Generated clean file layout.`, &quot;success&quot;);
            downloadBtn.disabled = false;

        } catch (err) {
            showStatus(&quot;Execution aborted: Corrupt xml layout detected inside your KML file.&quot;, &quot;info&quot;);
            console.error(err);
        }
    };
    reader.readAsText(file);
}

downloadBtn.addEventListener(&#39;click&#39;, function() {
    if (!optimizedKMLContent) return;
    const blob = new Blob([optimizedKMLContent], { type: &quot;application/vnd.google-earth.kml+xml&quot; });
    const link = document.createElement(&quot;a&quot;);
    link.href = URL.createObjectURL(blob);
    link.download = originalFileName;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
});

function showStatus(text, type) {
    const el = document.getElementById(&#39;status&#39;);
    el.innerText = text;
    el.style.display = &#39;block&#39;;
    el.className = &quot;status-box &quot; + type;
}
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/06/complext-to-simple-kml.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-3077069220461103986</guid><pubDate>Fri, 26 Jun 2026 10:06:59 +0000</pubDate><atom:updated>2026-06-30T08:22:57.193+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Roads</category><category domain="http://www.blogger.com/atom/ns#">Software</category><title>Road alignment Radius of Curvature check according to design speed</title><description>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;IRC Polynomial Curvature Geometry Checker&lt;/title&gt;

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js&quot;&gt;&lt;/script&gt;

&lt;style&gt;

body{
    font-family:Arial;
    background:#f2f4f7;
    margin:20px;
}

.container{
    max-width:1200px;
    margin:auto;
    background:white;
    padding:20px;
    border-radius:10px;
    box-shadow:0 0 10px rgba(0,0,0,0.15);
}

h2{
    color:#0056b3;
}

table{
    width:100%;
    border-collapse:collapse;
    margin-top:20px;
}

th,td{
    border:1px solid #ccc;
    padding:8px;
    text-align:center;
}

th{
    background:#0056b3;
    color:white;
}

.pass{
    background:#d4edda;
    color:green;
    font-weight:bold;
}

.fail{
    background:#f8d7da;
    color:red;
    font-weight:bold;
}

.summary{
    padding:15px;
    margin-top:20px;
    font-weight:bold;
}

button{
    padding:10px 20px;
    margin-top:20px;
    background:#28a745;
    color:white;
    border:none;
    border-radius:5px;
    cursor:pointer;
}

select{
    padding:8px;
}

&lt;/style&gt;
&lt;/head&gt;

&lt;body&gt;

&lt;div class=&quot;container&quot; id=&quot;reportContainer&quot;&gt;

&lt;h2&gt;IRC Horizontal Geometry Checker&lt;/h2&gt;

&lt;select id=&quot;terrain&quot;&gt;
    &lt;option value=&quot;plain&quot;&gt;Plain (100 km/h)&lt;/option&gt;
    &lt;option value=&quot;rolling&quot;&gt;Rolling (80 km/h)&lt;/option&gt;
    &lt;option value=&quot;mountainous&quot;&gt;Mountainous (50 km/h)&lt;/option&gt;
    &lt;option value=&quot;steep&quot;&gt;Steep (40 km/h)&lt;/option&gt;
&lt;/select&gt;

&lt;input type=&quot;file&quot; id=&quot;kmlFile&quot; accept=&quot;.kml&quot;&gt;

&lt;div id=&quot;summaryBox&quot;&gt;&lt;/div&gt;

&lt;table id=&quot;resultsTable&quot; style=&quot;display:none;&quot;&gt;

&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Point&lt;/th&gt;
&lt;th&gt;Longitude&lt;/th&gt;
&lt;th&gt;Latitude&lt;/th&gt;
&lt;th&gt;Radius (m)&lt;/th&gt;
&lt;th&gt;Superelevation (%)&lt;/th&gt;
&lt;th&gt;Transition Length (m)&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody id=&quot;resultsBody&quot;&gt;&lt;/tbody&gt;

&lt;/table&gt;

&lt;button onclick=&quot;exportPDF()&quot;&gt;Export PDF&lt;/button&gt;

&lt;/div&gt;
  
  &lt;div style=&quot;font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe UI&#39;, Roboto, Helvetica, Arial, sans-serif; color: #333; line-height: 1.6; max-width: 800px; margin: 0 auto; padding: 20px;&quot;&gt;
    
    &lt;h1 style=&quot;color: #0288d1; border-bottom: 2px solid #e1f5fe; padding-bottom: 10px; margin-bottom: 5px;&quot;&gt;User Guide: IRC Road Alignment Compliance Checker&lt;/h1&gt;
    &lt;p style=&quot;font-size: 14px; color: #757575; font-style: italic; margin-top: 0;&quot;&gt;Automated Geometric Design Evaluation Tool&lt;/p&gt;
    
    &lt;p style=&quot;font-size: 16px; color: #424242;&quot;&gt;
        This tool analyzes road centerlines from &lt;strong&gt;KML files&lt;/strong&gt; to verify alignment parameters against standard &lt;strong&gt;IRC (Indian Roads Congress)&lt;/strong&gt; design criteria. It computes curve radius, required superelevation, and transition spiral lengths in real-time.
    &lt;/p&gt;

    &lt;hr style=&quot;border: 0; border-top: 1px solid #e0e0e0; margin: 25px 0;&quot; /&gt;

    &lt;h2 style=&quot;color: #212121; font-size: 20px;&quot;&gt;IRC Design Standards Applied&lt;/h2&gt;
    &lt;p&gt;The tool evaluates your spatial data using a local coordinate projection ($R = 6,371\text{ km}$) and quadratic regression curves over a sliding 11-point mathematical window. The design thresholds are structured as follows:&lt;/p&gt;
    
    &lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 15px 0; font-size: 14px; text-align: left;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background-color: #f5f5f5; border-bottom: 2px solid #e0e0e0;&quot;&gt;
                &lt;th style=&quot;padding: 12px; font-weight: 600; color: #212121;&quot;&gt;Terrain Classification&lt;/th&gt;
                &lt;th style=&quot;padding: 12px; font-weight: 600; color: #212121;&quot;&gt;Design Speed ($V$)&lt;/th&gt;
                &lt;th style=&quot;padding: 12px; font-weight: 600; color: #212121;&quot;&gt;Min. Permissible Radius ($R_{min}$)&lt;/th&gt;
                &lt;th style=&quot;padding: 12px; font-weight: 600; color: #212121;&quot;&gt;Max. Superelevation ($e_{max}$)&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr style=&quot;border-bottom: 1px solid #eee;&quot;&gt;
                &lt;td style=&quot;padding: 10px; font-weight: 500;&quot;&gt;&lt;strong&gt;Plain&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;100 km/h&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;360 meters&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;7.00%&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;border-bottom: 1px solid #eee;&quot;&gt;
                &lt;td style=&quot;padding: 10px; font-weight: 500;&quot;&gt;&lt;strong&gt;Rolling&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;80 km/h&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;230 meters&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;7.00%&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;border-bottom: 1px solid #eee;&quot;&gt;
                &lt;td style=&quot;padding: 10px; font-weight: 500;&quot;&gt;&lt;strong&gt;Mountainous&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;50 km/h&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;90 meters&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;7.00%&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr style=&quot;border-bottom: 1px solid #eee;&quot;&gt;
                &lt;td style=&quot;padding: 10px; font-weight: 500;&quot;&gt;&lt;strong&gt;Steep&lt;/strong&gt;&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;40 km/h&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;60 meters&lt;/td&gt;
                &lt;td style=&quot;padding: 10px;&quot;&gt;7.00%&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;hr style=&quot;border: 0; border-top: 1px solid #e0e0e0; margin: 25px 0;&quot; /&gt;

    &lt;h2 style=&quot;color: #212121; font-size: 20px;&quot;&gt;Step-by-Step Instructions&lt;/h2&gt;
    
    &lt;div style=&quot;margin-bottom: 20px;&quot;&gt;
        &lt;span style=&quot;display: inline-block; background-color: #0288d1; color: white; padding: 2px 8px; border-radius: 3px; font-weight: bold; font-size: 12px; margin-bottom: 5px;&quot;&gt;STEP 1&lt;/span&gt;
        &lt;p style=&quot;margin: 0; padding-left: 5px; color: #424242;&quot;&gt;
            Select your project&#39;s geography type using the &lt;strong&gt;Terrain&lt;/strong&gt; drop-down menu. This loads the correct speed parameters and geometric rulesets.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;div style=&quot;margin-bottom: 20px;&quot;&gt;
        &lt;span style=&quot;display: inline-block; background-color: #0288d1; color: white; padding: 2px 8px; border-radius: 3px; font-weight: bold; font-size: 12px; margin-bottom: 5px;&quot;&gt;STEP 2&lt;/span&gt;
        &lt;p style=&quot;margin: 0; padding-left: 5px; color: #424242;&quot;&gt;
            Click on &lt;strong&gt;Choose File / Upload KML&lt;/strong&gt; and provide your file containing the path string. 
            &lt;br /&gt;&lt;small style=&quot;color: #e53935;&quot;&gt;*Note: The path alignment must contain &lt;strong&gt;at least 11 survey coordinate points&lt;/strong&gt; to enable the mathematical curvature checks.&lt;/small&gt;
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;div style=&quot;margin-bottom: 20px;&quot;&gt;
        &lt;span style=&quot;display: inline-block; background-color: #0288d1; color: white; padding: 2px 8px; border-radius: 3px; font-weight: bold; font-size: 12px; margin-bottom: 5px;&quot;&gt;STEP 3&lt;/span&gt;
        &lt;p style=&quot;margin: 0; padding-left: 5px; color: #424242;&quot;&gt;
            Review the generated engineering data layout. Look for the &lt;strong&gt;Summary Box&lt;/strong&gt; output at the base of your UI:
        &lt;/p&gt;
        &lt;ul style=&quot;margin: 5px 0 0 15px; padding: 0; color: #616161;&quot;&gt;
            &lt;li&gt;&lt;span style=&quot;color: #2e7d32; font-weight: bold;&quot;&gt;PASS / TANGENT:&lt;/span&gt; The segment satisfies IRC criteria or is a straight line ($R &gt; 10,000\text{ m}$).&lt;/li&gt;
            &lt;li&gt;&lt;span style=&quot;color: #c62828; font-weight: bold;&quot;&gt;FAIL:&lt;/span&gt; The curve is too sharp for the designated vehicle design speed.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;div style=&quot;margin-bottom: 20px;&quot;&gt;
        &lt;span style=&quot;display: inline-block; background-color: #0288d1; color: white; padding: 2px 8px; border-radius: 3px; font-weight: bold; font-size: 12px; margin-bottom: 5px;&quot;&gt;STEP 4&lt;/span&gt;
        &lt;p style=&quot;margin: 0; padding-left: 5px; color: #424242;&quot;&gt;
            Click the &lt;strong&gt;Export PDF Report&lt;/strong&gt; action button. The application calls an internal cloning window to format a clean, presentation-ready engineering spreadsheet report page directly to an A4 PDF document download.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;hr style=&quot;border: 0; border-top: 1px solid #e0e0e0; margin: 25px 0;&quot; /&gt;

    &lt;h2 style=&quot;color: #212121; font-size: 20px;&quot;&gt;Engineered Output Metric Calculations&lt;/h2&gt;
    &lt;p&gt;For every passing node, the tool computes two main structural highway design values:&lt;/p&gt;
    
    &lt;blockquote style=&quot;margin: 15px 0; padding: 10px 15px; background-color: #f9f9f9; border-left: 4px solid #b0bec5; font-size: 14px; color: #37474f;&quot;&gt;
        &lt;strong&gt;1. Equilibrium Superelevation ($e$):&lt;/strong&gt; Calculated using the structural formula:
        $$e = \frac{V^2}{225 \cdot R}$$
        The script automatically caps the output value at a maximum threshold of $7.00\%$ per standard mixed-traffic specifications.
    &lt;/blockquote&gt;

    &lt;blockquote style=&quot;margin: 15px 0; padding: 10px 15px; background-color: #f9f9f9; border-left: 4px solid #b0bec5; font-size: 14px; color: #37474f;&quot;&gt;
        &lt;strong&gt;2. Transition Spiral Curve Length ($L_s$):&lt;/strong&gt; Derived from the comfort rate of acceleration parameters:
        $$L_s = \frac{0.0215 \cdot V^3}{80 \cdot R}$$
        This defines the safe length requirement over which the highway cross-slope shifts from a normal crown to a fully elevated state.
    &lt;/blockquote&gt;

    &lt;div style=&quot;margin-top: 30px; padding: 12px; background-color: #efebe9; border-radius: 4px; border: 1px solid #d7ccc8;&quot;&gt;
        &lt;p style=&quot;margin: 0; font-size: 12px; color: #4e342e; text-align: center;&quot;&gt;
            &lt;strong&gt;System Engine:&lt;/strong&gt; Requires the &lt;code&gt;html2pdf&lt;/code&gt; dependency library available in your application wrapper template window to build structural report exports.
        &lt;/p&gt;
    &lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;

const irc = {
    plain:{speed:100,minR:360},
    rolling:{speed:80,minR:230},
    mountainous:{speed:50,minR:90},
    steep:{speed:40,minR:60}
};

document.getElementById(&quot;kmlFile&quot;)
.addEventListener(&quot;change&quot;,loadKML);

function loadKML(e){

    const file=e.target.files[0];

    if(!file) return;

    const reader=new FileReader();

    reader.onload=function(evt){

        const parser=new DOMParser();

        const xml=parser.parseFromString(
            evt.target.result,
            &quot;text/xml&quot;
        );

        const nodes=
            xml.getElementsByTagName(&quot;coordinates&quot;);

        let coords=[];

        for(let i=0;i&lt;nodes.length;i++){

            const txt=
                nodes[i].textContent.trim();

            const pairs=
                txt.split(/[\s\n\r]+/);

            pairs.forEach(p=&gt;{

                const a=p.split(&quot;,&quot;);

                if(a.length&gt;=2){

                    const lon=parseFloat(a[0]);
                    const lat=parseFloat(a[1]);

                    if(!isNaN(lat))
                        coords.push({lon,lat});
                }
            });
        }

        if(coords.length&lt;11){

            alert(&quot;Minimum 11 points required.&quot;);

            return;
        }

        process(coords);
    };

    reader.readAsText(file);
}

function toXY(lon,lat,lon0,lat0){

    const R=6371000;

    const x=R*
        (lon-lon0)*
        Math.PI/180*
        Math.cos(lat0*Math.PI/180);

    const y=R*
        (lat-lat0)*
        Math.PI/180;

    return {x,y};
}

function gaussian(A,B){

    const n=B.length;

    for(let i=0;i&lt;n;i++){

        let max=i;

        for(let j=i+1;j&lt;n;j++){

            if(Math.abs(A[j][i])&gt;
               Math.abs(A[max][i]))
                max=j;
        }

        [A[i],A[max]]=[A[max],A[i]];
        [B[i],B[max]]=[B[max],B[i]];

        for(let j=i+1;j&lt;n;j++){

            const f=A[j][i]/A[i][i];

            for(let k=i;k&lt;n;k++)
                A[j][k]-=f*A[i][k];

            B[j]-=f*B[i];
        }
    }

    let x=Array(n).fill(0);

    for(let i=n-1;i&gt;=0;i--){

        x[i]=B[i];

        for(let j=i+1;j&lt;n;j++)
            x[i]-=A[i][j]*x[j];

        x[i]/=A[i][i];
    }

    return x;
}

function fitQuadratic(points){

    let sx=0,sx2=0,sx3=0,sx4=0;

    let sy=0,sxy=0,sx2y=0;

    const n=points.length;

    points.forEach(p=&gt;{

        const x=p.x;
        const y=p.y;

        sx+=x;
        sx2+=x*x;
        sx3+=x*x*x;
        sx4+=x*x*x*x;

        sy+=y;
        sxy+=x*y;
        sx2y+=x*x*y;
    });

    const A=[
        [n,sx,sx2],
        [sx,sx2,sx3],
        [sx2,sx3,sx4]
    ];

    const B=[sy,sxy,sx2y];

    return gaussian(A,B);
}

function curvature(coeff,x){

    const a=coeff[2];
    const b=coeff[1];

    const y1=2*a*x+b;

    const y2=2*a;

    if(Math.abs(y2)&lt;1e-8)
        return 999999;

    return Math.pow(
        1+y1*y1,
        1.5
    )/Math.abs(y2);
}

function superelevation(V,R){

    let e=(V*V)/(225*R);

    if(e&gt;0.07)
        e=0.07;

    return e*100;
}

function transition(V,R){

    return (0.0215*V*V*V)/(80*R);
}

function process(coords){

    const terrain=
        document.getElementById(&quot;terrain&quot;).value;

    const std=irc[terrain];

    const V=std.speed;

    const lon0=coords[0].lon;
    const lat0=coords[0].lat;

    const xy=
        coords.map(c=&gt;
            toXY(c.lon,c.lat,lon0,lat0)
        );

    const tbody=
        document.getElementById(
            &quot;resultsBody&quot;
        );

    tbody.innerHTML=&quot;&quot;;

    let fail=0;

    for(let i=5;i&lt;xy.length-5;i++){

        let local=[];

        for(let j=i-5;j&lt;=i+5;j++){

            local.push({
                x:xy[j].x-xy[i].x,
                y:xy[j].y-xy[i].y
            });
        }

        const coeff=
            fitQuadratic(local);

        const R=
            curvature(coeff,0);

        const e=
            superelevation(V,R);

        const Ls=
            transition(V,R);

        let cls=&quot;pass&quot;;
        let status=&quot;PASS&quot;;

        if(R&lt;std.minR){

            cls=&quot;fail&quot;;

            status=&quot;FAIL&quot;;

            fail++;
        }

        if(R&gt;10000){

            status=&quot;TANGENT&quot;;

            cls=&quot;&quot;;
        }

        tbody.innerHTML+=`
        &lt;tr&gt;
        &lt;td&gt;${i}&lt;/td&gt;
        &lt;td&gt;${coords[i].lon.toFixed(6)}&lt;/td&gt;
        &lt;td&gt;${coords[i].lat.toFixed(6)}&lt;/td&gt;
        &lt;td&gt;${R.toFixed(1)}&lt;/td&gt;
        &lt;td&gt;${e.toFixed(2)}&lt;/td&gt;
        &lt;td&gt;${Ls.toFixed(1)}&lt;/td&gt;
        &lt;td class=&quot;${cls}&quot;&gt;
        ${status}
        &lt;/td&gt;
        &lt;/tr&gt;
        `;
    }

    document.getElementById(
        &quot;resultsTable&quot;
    ).style.display=&quot;table&quot;;

    const summary=
        document.getElementById(
            &quot;summaryBox&quot;
        );

    if(fail&gt;0){

        summary.className=
            &quot;summary fail&quot;;

        summary.innerHTML=
            `${fail} locations violate IRC radius requirements.`;
    }
    else{

        summary.className=
            &quot;summary pass&quot;;

        summary.innerHTML=
            &quot;Alignment satisfies IRC requirements.&quot;;
    }
}

function exportPDF() {

    const original = document.getElementById(&quot;reportContainer&quot;);

    // Create clone
    const clone = original.cloneNode(true);

    // Remove unnecessary controls
    const fileInput = clone.querySelector(&quot;#kmlFile&quot;);
    if(fileInput) fileInput.remove();

    // Replace select by text
    const terrainSelect =
        document.getElementById(&quot;terrain&quot;);

    const terrainText =
        terrainSelect.options[
            terrainSelect.selectedIndex
        ].text;

    const clonedSelect =
        clone.querySelector(&quot;#terrain&quot;);

    if(clonedSelect){

        const span=document.createElement(&quot;div&quot;);

        span.innerHTML =
            &quot;&lt;b&gt;Terrain:&lt;/b&gt; &quot; +
            terrainText;

        span.style.marginBottom=&quot;10px&quot;;

        clonedSelect.parentNode.replaceChild(
            span,
            clonedSelect
        );
    }

    // Put clone temporarily into DOM
    const holder=document.createElement(&quot;div&quot;);

    holder.style.position=&quot;absolute&quot;;
    holder.style.left=&quot;-9999px&quot;;
    holder.style.top=&quot;0&quot;;
    holder.style.width=&quot;1400px&quot;;

    holder.appendChild(clone);

    document.body.appendChild(holder);

    const options={

        margin:10,

        filename:&quot;IRC_Report.pdf&quot;,

        image:{
            type:&quot;jpeg&quot;,
            quality:1
        },

        html2canvas:{
            scale:2,
            useCORS:true,
            scrollX:0,
            scrollY:0,
            windowWidth:1400,
            windowHeight:clone.scrollHeight
        },

        jsPDF:{
            unit:&quot;mm&quot;,
            format:&quot;a4&quot;,
            orientation:&quot;landscape&quot;
        },

        pagebreak:{
            mode:[&quot;css&quot;,&quot;legacy&quot;]
        }
    };

    setTimeout(function(){

        html2pdf()
        .set(options)
        .from(clone)
        .save()
        .then(function(){

            document.body.removeChild(holder);

        });

    },300);
}
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/06/road-alignment-radius-of-curvature.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-6407646585304885879</guid><pubDate>Tue, 02 Jun 2026 13:08:02 +0000</pubDate><atom:updated>2026-06-23T14:05:19.678+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Construction Procedure</category><category domain="http://www.blogger.com/atom/ns#">Programming</category><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><title>Project tasks report </title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Project &amp; Task Lifecycle Tracker&lt;/title&gt;
    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.6.0/jspdf.plugin.autotable.min.js&quot;&gt;&lt;/script&gt;
    
&lt;style&gt;
    /* --- CSS Variables Configuration --- */
    :root {
        --primary-color: #0056b3;
        --secondary-color: #6c757d;
        --danger-color: #dc3545;
        --success-color: #28a745;
        --warning-color: #ffc107;
        --light-bg: #f8f9fa;
        --border-color: #dee2e6;
    }

    /* --- Core Container Setup --- */
    .tracker-container {
        font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Arial, sans-serif;
        color: #333;
        max-width: 1100px;
        margin: 20px auto;
        padding: 15px;
        background: #ffffff;
        border-radius: 8px;
        box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    }

    /* --- Typography Scope Isolation --- */
    .tracker-container h1 {
        color: var(--primary-color);
        margin-bottom: 5px;
    }

    .tracker-container h2, 
    .tracker-container h3 {
        color: #222;
        border-bottom: 2px solid var(--light-bg);
        padding-bottom: 8px;
        margin-top: 25px;
    }

    .tracker-container header {
        border-bottom: 2px solid var(--border-color);
        padding-bottom: 15px;
        margin-bottom: 30px;
    }

    /* --- Form Elements --- */
    .form-group {
        margin-bottom: 15px;
    }

    .form-group label {
        display: block;
        font-weight: bold;
        margin-bottom: 5px;
    }

    .form-control {
        width: 100%;
        padding: 8px;
        border: 1px solid var(--border-color);
        border-radius: 4px;
        box-sizing: border-box;
    }

    /* --- Layout Components --- */
    .project-section, .task-section {
        background: var(--light-bg);
        padding: 15px;
        border-radius: 6px;
        margin-bottom: 20px;
        border: 1px solid var(--border-color);
    }

    .grid-2 {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 15px;
    }

    /* --- Button Architectures --- */
    .btn-group {
        display: flex;
        gap: 10px;
        margin-top: 10px;
        flex-wrap: wrap;
    }

    .btn {
        padding: 6px 12px;
        border: none;
        border-radius: 4px;
        cursor: pointer;
        font-weight: 500;
        color: #fff;
        font-size: 0.9em;
        transition: opacity 0.15s ease;
    }

    .btn:hover { opacity: 0.9; }
    .btn:disabled { opacity: 0.5; cursor: not-allowed; }

    .btn-primary { background-color: var(--primary-color); }
    .btn-danger { background-color: var(--danger-color); }
    .btn-success { background-color: var(--success-color); }
    .btn-secondary { background-color: var(--secondary-color); }

    /* --- Table Core Grid --- */
    table {
        width: 100%;
        border-collapse: collapse;
        margin-top: 15px;
        background: #fff;
    }

    th, td {
        border: 1px solid var(--border-color);
        padding: 10px;
        text-align: left;
        vertical-align: top;
    }

    th { background-color: #f1f3f5; }

    /* --- Status Pill Badges --- */
    .status-badge {
        padding: 4px 8px;
        border-radius: 12px;
        font-size: 0.8em;
        font-weight: bold;
        cursor: pointer;
        display: inline-block;
        transition: all 0.2s ease;
        user-select: none;
        border: 1px solid transparent;
        white-space: nowrap;
    }
    
    .status-pending { background-color: #ffeeba; color: #856404; border-color: #ffe082; }
    .status-pending:hover { background-color: #ffd54f; }

    .status-completed { background-color: #d4edda; color: #155724; border-color: #c3e6cb; }
    .status-completed:hover { background-color: #a5d6a7; }

    /* Static Document Badges */
    .badge {
        display: inline-block;
        padding: 2px 6px;
        font-size: 0.8rem;
        font-weight: 600;
        border-radius: 4px;
        color: #fff;
    }
    .badge-blue { background-color: var(--primary-color); }
    .badge-green { background-color: var(--success-color); }
    .badge-red { background-color: var(--danger-color); }
    .badge-gray { background-color: var(--secondary-color); }

    /* --- Subtask Matrix Column Layout --- */
    .subtask-column-layout {
        display: flex;
        flex-direction: column;
        gap: 6px;
    }

    .subtask-row {
        display: grid;
        grid-template-columns: 2fr 1.2fr 1.2fr auto;
        gap: 8px;
        align-items: center;
        background: #fdfdfd;
        padding: 6px;
        border: 1px dashed #ced4da;
        border-radius: 4px;
    }

    .subtask-input-bar {
        display: grid;
        grid-template-columns: 2fr 1.2fr auto;
        gap: 8px;
        margin-top: 10px;
        padding-top: 10px;
        border-top: 1px solid var(--border-color);
    }

    .subtask-input-bar input {
        padding: 5px;
        font-size: 0.85em;
        border: 1px solid var(--border-color);
        border-radius: 4px;
        width: 100%;
        box-sizing: border-box;
    }

    /* --- Documentation Elements --- */
    .highlight-box {
        background-color: #e8f4fd;
        border-left: 4px solid var(--primary-color);
        padding: 15px;
        border-radius: 4px;
        margin: 20px 0;
    }

    .danger-box {
        background-color: #fdf2f2;
        border-left: 4px solid var(--danger-color);
        padding: 15px;
        border-radius: 4px;
        margin: 20px 0;
    }

    code {
        font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, monospace;
        background-color: #f1f3f5;
        padding: 2px 6px;
        border-radius: 4px;
        font-size: 0.9em;
    }

    .info-tip {
        font-size: 0.85em;
        color: #6c757d;
        margin-top: 5px;
        font-style: italic;
    }

    ol, ul { padding-left: 20px; }
    li { margin-bottom: 8px; }

    footer {
        margin-top: 50px;
        padding-top: 20px;
        border-top: 1px solid var(--border-color);
        font-size: 0.85rem;
        text-align: center;
        color: var(--secondary-color);
    }

    /* --- Fluid Mobile Responsiveness Breakpoints --- */
    @media (max-width: 768px) {
        .grid-2 { 
            grid-template-columns: 1fr; 
        }
        .subtask-row, 
        .subtask-input-bar {
            grid-template-columns: 1fr;
            gap: 4px;
        }
        .subtask-row &gt; * {
            width: 100%;
        }
    }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;tracker-container&quot;&gt;
    &lt;h2&gt;Project &amp; Task Lifecycle Tracker&lt;/h2&gt;

    &lt;div class=&quot;project-section&quot;&gt;
        &lt;div class=&quot;form-group&quot;&gt;
            &lt;label for=&quot;projectSelect&quot;&gt;Select Project:&lt;/label&gt;
            &lt;select id=&quot;projectSelect&quot; class=&quot;form-control&quot; onchange=&quot;loadSelectedProject()&quot;&gt;
                &lt;option value=&quot;&quot;&gt;-- Choose a Project --&lt;/option&gt;
            &lt;/select&gt;
        &lt;/div&gt;
        &lt;div class=&quot;btn-group&quot;&gt;
            &lt;button class=&quot;btn btn-secondary&quot; onclick=&quot;showNewProjectForm()&quot;&gt;+ Create New Project&lt;/button&gt;
            &lt;button id=&quot;editProjBtn&quot; class=&quot;btn btn-primary&quot; onclick=&quot;enableProjectEdit()&quot; disabled&gt;Edit Project Name&lt;/button&gt;
            &lt;button id=&quot;deleteProjBtn&quot; class=&quot;btn btn-danger&quot; onclick=&quot;deleteCurrentProject()&quot; disabled&gt;Delete Entire Project&lt;/button&gt;
            &lt;button id=&quot;pdfBtn&quot; class=&quot;btn btn-success&quot; onclick=&quot;exportToPDF()&quot; disabled&gt;Export Status Report (PDF)&lt;/button&gt;
        &lt;/div&gt;

        &lt;div id=&quot;projectForm&quot; style=&quot;display:none; margin-top:15px; padding-top:15px; border-top:1px dashed #ccc;&quot;&gt;
            &lt;div class=&quot;form-group&quot;&gt;
                &lt;label id=&quot;projFormLabel&quot; for=&quot;projectNameInput&quot;&gt;Project Name:&lt;/label&gt;
                &lt;input type=&quot;text&quot; id=&quot;projectNameInput&quot; class=&quot;form-control&quot; placeholder=&quot;Enter project name&quot;&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn btn-success&quot; onclick=&quot;saveProject()&quot;&gt;Save Project&lt;/button&gt;
            &lt;button class=&quot;btn btn-secondary&quot; onclick=&quot;cancelProjectForm()&quot;&gt;Cancel&lt;/button&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div id=&quot;taskWorkspace&quot; style=&quot;display: none;&quot;&gt;
        &lt;div class=&quot;task-section&quot;&gt;
            &lt;h3&gt;Add New Main Task&lt;/h3&gt;
            &lt;div class=&quot;form-group&quot;&gt;
                &lt;label for=&quot;taskName&quot;&gt;Main Task Description:&lt;/label&gt;
                &lt;input type=&quot;text&quot; id=&quot;taskName&quot; class=&quot;form-control&quot; placeholder=&quot;What needs to be done?&quot;&gt;
            &lt;/div&gt;
            &lt;div class=&quot;grid-2&quot;&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label for=&quot;taskDeadline&quot;&gt;Deadline:&lt;/label&gt;
                    &lt;input type=&quot;date&quot; id=&quot;taskDeadline&quot; class=&quot;form-control&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label for=&quot;taskStatus&quot;&gt;Status:&lt;/label&gt;
                    &lt;select id=&quot;taskStatus&quot; class=&quot;form-control&quot; onchange=&quot;toggleCompletionDate()&quot;&gt;
                        &lt;option value=&quot;Pending&quot;&gt;Pending&lt;/option&gt;
                        &lt;option value=&quot;Completed&quot;&gt;Completed&lt;/option&gt;
                    &lt;/select&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;form-group&quot; id=&quot;completionDateGroup&quot; style=&quot;display: none;&quot;&gt;
                &lt;label for=&quot;taskCompletionDate&quot;&gt;Date of Completion:&lt;/label&gt;
                &lt;input type=&quot;date&quot; id=&quot;taskCompletionDate&quot; class=&quot;form-control&quot;&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn btn-primary&quot; onclick=&quot;saveTask()&quot;&gt;Add Main Task&lt;/button&gt;
        &lt;/div&gt;

        &lt;h3&gt;Task Matrix&lt;/h3&gt;
        &lt;p class=&quot;info-tip&quot;&gt;💡 Tip: Click directly on any status badge (Main Task or Subtask) to flip its status instantly.&lt;/p&gt;
        &lt;div style=&quot;overflow-x: auto;&quot;&gt;
            &lt;table id=&quot;taskTable&quot;&gt;
                &lt;thead&gt;
                    &lt;tr&gt;
                        &lt;th style=&quot;width: 25%;&quot;&gt;Main Task Description&lt;/th&gt;
                        &lt;th style=&quot;width: 45%;&quot;&gt;Subtasks Structure (Description | Deadline | Status | Action)&lt;/th&gt;
                        &lt;th style=&quot;width: 10%;&quot;&gt;Main Deadline&lt;/th&gt;
                        &lt;th style=&quot;width: 10%;&quot;&gt;Main Status&lt;/th&gt;
                        &lt;th style=&quot;width: 10%;&quot;&gt;Main Comp. Date&lt;/th&gt;
                        &lt;th style=&quot;width: 5%;&quot;&gt;Action&lt;/th&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody id=&quot;taskTableBody&quot;&gt;
                    &lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
  
  &lt;header&gt;
        &lt;h1&gt;Project &amp; Task Lifecycle Tracker&lt;/h1&gt;
        &lt;p class=&quot;meta-info&quot;&gt;Official User Guide &amp; Technical Documentation&lt;/p&gt;
    &lt;/header&gt;

    &lt;section id=&quot;introduction&quot;&gt;
        &lt;h2&gt;1. Introduction&lt;/h2&gt;
        &lt;p&gt;The &lt;strong&gt;Project &amp; Task Lifecycle Tracker&lt;/strong&gt; is an enterprise-grade, single-page application built to structure complex project workflows into digestible, relational milestones. Designed for professionals managing infrastructure tasks and rigorous timelines, this utility supports a parent-child relationship hierarchy (Main Tasks &amp; Subtasks) alongside robust data isolation capabilities.&lt;/p&gt;
        
        &lt;div class=&quot;highlight-box&quot;&gt;
            &lt;strong&gt;Key Feature: Localized Architecture&lt;/strong&gt;&lt;br&gt;
            Unlike traditional tracking tools that depend on external server environments or third-party cloud cookies, this application runs entirely client-side. Your operational data remains securely inside your browser profile.
        &lt;/div&gt;
    &lt;/section&gt;

    &lt;section id=&quot;technical-architecture&quot;&gt;
        &lt;h2&gt;2. Data Engine &amp; Technical Architecture&lt;/h2&gt;
        &lt;p&gt;To operate reliably offline and store large datasets without performance bottlenecks, the tool leverages the browser&#39;s native &lt;strong&gt;IndexedDB API&lt;/strong&gt;. Here is how the underlying mechanism handles your input:&lt;/p&gt;
        
        &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;Database Schema:&lt;/strong&gt; Operates under the storage identity &lt;code&gt;YogiPWD_SubtaskTrackerDB_v2&lt;/code&gt;.&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Relational Mapping:&lt;/strong&gt; It isolates records across two main internal tables (Object Stores):
                &lt;ul&gt;
                    &lt;li&gt;&lt;code&gt;projects&lt;/code&gt;: Stores the primary master containers using an auto-incremented key configuration.&lt;/li&gt;
                    &lt;li&gt;&lt;code&gt;tasks&lt;/code&gt;: Stores core task rows indexed directly by a &lt;code&gt;projectId&lt;/code&gt; foreign key to guarantee relational integrity.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Subtask Structuring:&lt;/strong&gt; Subtasks are systematically embedded directly into their respective parent task arrays. This structural nesting facilitates instantaneous localized updates and prevents orphaned data records.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/section&gt;

    &lt;section id=&quot;user-guide&quot;&gt;
        &lt;h2&gt;3. Step-by-Step Functional Guide&lt;/h2&gt;
        
        &lt;h3&gt;3.1 Initializing a Workspace&lt;/h3&gt;
        &lt;p&gt;When you open the application, the task matrix remains hidden until an explicit workspace scope is designated:&lt;/p&gt;
        &lt;ol&gt;
            &lt;li&gt;Click the &lt;span class=&quot;badge badge-gray&quot;&gt;+ Create New Project&lt;/span&gt; button.&lt;/li&gt;
            &lt;li&gt;Type your specific project banner or work order name into the dynamically exposed configuration input field.&lt;/li&gt;
            &lt;li&gt;Click &lt;strong&gt;Save Project&lt;/strong&gt;. The workspace immediately shifts focus to your newly initialized project.&lt;/li&gt;
        &lt;/ol&gt;

        &lt;h3&gt;3.2 Managing Core Components&lt;/h3&gt;
        &lt;p&gt;Once a project is active, you can leverage the top control panel layout:&lt;/p&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;Edit Project Name:&lt;/strong&gt; Modifies the active project identity without altering any task rows nested underneath it.&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Delete Entire Project:&lt;/strong&gt; &lt;span class=&quot;badge badge-red&quot;&gt;Danger Area&lt;/span&gt; This triggers a recursive transactional cascade. Confirming this action permanently deletes the project container, its main metrics, and all associated subtask blocks from the database.&lt;/li&gt;
        &lt;/ul&gt;

        &lt;h3&gt;3.3 Populating the Task Matrix&lt;/h3&gt;
        &lt;p&gt;The &lt;strong&gt;Add New Main Task&lt;/strong&gt; form accepts primary activity entries. To populate it:&lt;/p&gt;
        &lt;ol&gt;
            &lt;li&gt;Provide a &lt;strong&gt;Main Task Description&lt;/strong&gt; (e.g., &lt;em&gt;&quot;Procurement Validation&quot;&lt;/em&gt; or &lt;em&gt;&quot;Site Alignment Inspection&quot;&lt;/em&gt;).&lt;/li&gt;
            &lt;li&gt;Set a primary calendar &lt;strong&gt;Deadline&lt;/strong&gt;.&lt;/li&gt;
            &lt;li&gt;Assign an initial lifecycle phase status (&lt;span class=&quot;badge badge-gray&quot;&gt;Pending&lt;/span&gt; or &lt;span class=&quot;badge badge-green&quot;&gt;Completed&lt;/span&gt;). If &lt;code&gt;Completed&lt;/code&gt; is chosen, a localized date input field will appear to log the verification timeline.&lt;/li&gt;
            &lt;li&gt;Click &lt;strong&gt;Add Main Task&lt;/strong&gt; to instantly append the entry into the primary tracking table.&lt;/li&gt;
        &lt;/ol&gt;

        &lt;h3&gt;3.4 Building the Subtask Structure&lt;/h3&gt;
        &lt;p&gt;Each main task row contains a nested data-entry column designed for breakdown logging:&lt;/p&gt;
        &lt;ul&gt;
            &lt;li&gt;Locate the input strip immediately below the main task row details.&lt;/li&gt;
            &lt;li&gt;Type out specific granular subtasks, specify their isolated due dates, and click the &lt;strong&gt;+ Add&lt;/strong&gt; button.&lt;/li&gt;
            &lt;li&gt;The system assigns a high-resolution microscopic timestamp identifier (&lt;code&gt;Date.now()&lt;/code&gt;) to every subtask block to ensure unique event tracking.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/section&gt;

    &lt;section id=&quot;advanced-interactions&quot;&gt;
        &lt;h2&gt;4. Advanced Interaction &amp; Quick Shortcuts&lt;/h2&gt;
        
        &lt;h3&gt;4.1 Instant Status Flipping&lt;/h3&gt;
        &lt;p&gt;For high-speed updates during site briefings or coordination reviews, you do not need to open complex edit menus. The interface provides &lt;strong&gt;Inline State Flipping&lt;/strong&gt;:&lt;/p&gt;
        &lt;div class=&quot;highlight-box&quot; style=&quot;background-color: #fffbeb; border-left-color: #f59e0b;&quot;&gt;
            &lt;strong&gt;Shortcut:&lt;/strong&gt; Click directly on any status badge display (e.g., &lt;code style=&quot;background-color: #fef3c7;&quot;&gt;Pending ⇄&lt;/code&gt;) in the matrix grid. The underlying database engine instantly switches its execution state.
        &lt;/div&gt;
        &lt;ul&gt;
            &lt;li&gt;Flipping to &lt;code&gt;Completed&lt;/code&gt; prompts a native system confirmation box requesting the completion calendar date (defaults automatically to the current date).&lt;/li&gt;
            &lt;li&gt;Reverting an item from &lt;code&gt;Completed&lt;/code&gt; back to &lt;code&gt;Pending&lt;/code&gt; automatically clears the corresponding completion date field.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/section&gt;

    &lt;section id=&quot;reporting-outputs&quot;&gt;
        &lt;h2&gt;5. Structured PDF Status Reports&lt;/h2&gt;
        &lt;p&gt;When stakeholders or senior management require an update, click the &lt;span class=&quot;badge badge-green&quot;&gt;Export Status Report (PDF)&lt;/span&gt; utility button. The reporting engine automatically generates a professional, dual-tier audit document using the following layout parameters:&lt;/p&gt;

        &lt;table&gt;
            &lt;thead&gt;
                &lt;tr&gt;
                    &lt;th&gt;Report Section&lt;/th&gt;
                    &lt;th&gt;Color Code&lt;/th&gt;
                    &lt;th&gt;Data Inclusion Mapping&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr&gt;
                    &lt;td&gt;&lt;strong&gt;1. Remaining / Pending Tasks&lt;/strong&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;span class=&quot;badge badge-red&quot;&gt;Red Header&lt;/span&gt;&lt;/td&gt;
                    &lt;td&gt;Lists incomplete parent tasks and individual active subtask rows waiting for validation.&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td&gt;&lt;strong&gt;2. Completed Achievements&lt;/strong&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;span class=&quot;badge badge-green&quot;&gt;Green Header&lt;/span&gt;&lt;/td&gt;
                    &lt;td&gt;Isolates finalized milestones along with their confirmed dates of completion.&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;

        &lt;p&gt;The generated PDF automatically handles name sanitization, converting special characters into clean underscores (&lt;code&gt;_&lt;/code&gt;) to output clean, storage-friendly file naming conventions.&lt;/p&gt;
    &lt;/section&gt;

    &lt;footer&gt;
        &lt;p&gt;Project &amp; Task Lifecycle Tracker Technical Manual — Built for Engineers and Project Managers.&lt;/p&gt;
    &lt;/footer&gt;

&lt;script&gt;
    // --- IndexedDB Management ---
    const DB_NAME = &#39;YogiPWD_SubtaskTrackerDB_v2&#39;;
    const DB_VERSION = 1;
    let db;

    const request = indexedDB.open(DB_NAME, DB_VERSION);

    request.onerror = function(e) { console.error(&quot;Database error: &quot;, e.target.error); };
    request.onsuccess = function(e) {
        db = e.target.result;
        initProjectDropdown();
    };

    request.onupgradeneeded = function(e) {
        let dbInstance = e.target.result;
        if (!dbInstance.objectStoreNames.contains(&#39;projects&#39;)) {
            dbInstance.createObjectStore(&#39;projects&#39;, { keyPath: &#39;id&#39;, autoIncrement: true });
        }
        if (!dbInstance.objectStoreNames.contains(&#39;tasks&#39;)) {
            let taskStore = dbInstance.createObjectStore(&#39;tasks&#39;, { keyPath: &#39;id&#39;, autoIncrement: true });
            taskStore.createIndex(&#39;projectId&#39;, &#39;projectId&#39;, { unique: false });
        }
    };

    let currentProjectId = null;
    let isEditingProject = false;

    // --- Project Logics ---
    function initProjectDropdown() {
        const transaction = db.transaction([&#39;projects&#39;], &#39;readonly&#39;);
        const store = transaction.objectStore(&#39;projects&#39;);
        const request = store.getAll();

        request.onsuccess = function() {
            const dropdown = document.getElementById(&#39;projectSelect&#39;);
            dropdown.innerHTML = &#39;&lt;option value=&quot;&quot;&gt;-- Choose a Project --&lt;/option&gt;&#39;;
            request.result.forEach(project =&gt; {
                let option = document.createElement(&#39;option&#39;);
                option.value = project.id;
                option.textContent = project.name;
                dropdown.appendChild(option);
            });
            if(currentProjectId) dropdown.value = currentProjectId;
        };
    }

    function showNewProjectForm() {
        isEditingProject = false;
        document.getElementById(&#39;projFormLabel&#39;).textContent = &quot;New Project Name:&quot;;
        document.getElementById(&#39;projectNameInput&#39;).value = &quot;&quot;;
        document.getElementById(&#39;projectForm&#39;).style.display = &#39;block&#39;;
    }

    function enableProjectEdit() {
        if (!currentProjectId) return;
        isEditingProject = true;
        document.getElementById(&#39;projFormLabel&#39;).textContent = &quot;Edit Project Name:&quot;;
        const dropdown = document.getElementById(&#39;projectSelect&#39;);
        document.getElementById(&#39;projectNameInput&#39;).value = dropdown.options[dropdown.selectedIndex].text;
        document.getElementById(&#39;projectForm&#39;).style.display = &#39;block&#39;;
    }

    function cancelProjectForm() {
        document.getElementById(&#39;projectForm&#39;).style.display = &#39;none&#39;;
    }

    function saveProject() {
        const name = document.getElementById(&#39;projectNameInput&#39;).value.trim();
        if (!name) return alert(&quot;Please enter a valid project name.&quot;);

        const transaction = db.transaction([&#39;projects&#39;], &#39;readwrite&#39;);
        const store = transaction.objectStore(&#39;projects&#39;);

        if (isEditingProject &amp;&amp; currentProjectId) {
            store.put({ id: currentProjectId, name: name }).onsuccess = function() {
                cancelProjectForm();
                initProjectDropdown();
            };
        } else {
            store.add({ name: name }).onsuccess = function(e) {
                currentProjectId = e.target.result;
                cancelProjectForm();
                initProjectDropdown();
                setTimeout(() =&gt; {
                    document.getElementById(&#39;projectSelect&#39;).value = currentProjectId;
                    loadSelectedProject();
                }, 100);
            };
        }
    }

    function deleteCurrentProject() {
        if (!currentProjectId) return;
        if (!confirm(&quot;Delete this project, its main tasks, and all subtasks permanently?&quot;)) return;

        const transaction = db.transaction([&#39;projects&#39;, &#39;tasks&#39;], &#39;readwrite&#39;);
        transaction.objectStore(&#39;projects&#39;).delete(currentProjectId);

        const taskStore = transaction.objectStore(&#39;tasks&#39;);
        const index = taskStore.index(&#39;projectId&#39;);
        index.openCursor(IDBKeyRange.only(currentProjectId)).onsuccess = function(e) {
            let cursor = e.target.result;
            if (cursor) {
                cursor.delete();
                cursor.continue();
            }
        };

        transaction.oncomplete = function() {
            currentProjectId = null;
            document.getElementById(&#39;taskWorkspace&#39;).style.display = &#39;none&#39;;
            toggleProjectControlButtons(false);
            initProjectDropdown();
        };
    }

    function loadSelectedProject() {
        const val = document.getElementById(&#39;projectSelect&#39;).value;
        if (!val) {
            currentProjectId = null;
            document.getElementById(&#39;taskWorkspace&#39;).style.display = &#39;none&#39;;
            toggleProjectControlButtons(false);
            return;
        }
        currentProjectId = parseInt(val);
        toggleProjectControlButtons(true);
        document.getElementById(&#39;taskWorkspace&#39;).style.display = &#39;block&#39;;
        renderTasks();
    }

    function toggleProjectControlButtons(enabled) {
        document.getElementById(&#39;editProjBtn&#39;).disabled = !enabled;
        document.getElementById(&#39;deleteProjBtn&#39;).disabled = !enabled;
        document.getElementById(&#39;pdfBtn&#39;).disabled = !enabled;
    }

    // --- Task &amp; Subtask Logics ---
    function toggleCompletionDate() {
        const status = document.getElementById(&#39;taskStatus&#39;).value;
        const dateGroup = document.getElementById(&#39;completionDateGroup&#39;);
        if (status === &#39;Completed&#39;) {
            dateGroup.style.display = &#39;block&#39;;
            document.getElementById(&#39;taskCompletionDate&#39;).value = new Date().toISOString().split(&#39;T&#39;)[0];
        } else {
            dateGroup.style.display = &#39;none&#39;;
            document.getElementById(&#39;taskCompletionDate&#39;).value = &quot;&quot;;
        }
    }

    function saveTask() {
        const name = document.getElementById(&#39;taskName&#39;).value.trim();
        const deadline = document.getElementById(&#39;taskDeadline&#39;).value;
        const status = document.getElementById(&#39;taskStatus&#39;).value;
        let compDate = document.getElementById(&#39;taskCompletionDate&#39;).value;

        if (!name || !deadline) return alert(&quot;Task description and deadline are required.&quot;);

        const taskItem = {
            projectId: currentProjectId,
            name: name,
            deadline: deadline,
            status: status,
            completionDate: status === &#39;Completed&#39; ? compDate : &quot;&quot;,
            subtasks: []
        };

        const transaction = db.transaction([&#39;tasks&#39;], &#39;readwrite&#39;);
        transaction.objectStore(&#39;tasks&#39;).add(taskItem).onsuccess = function() {
            document.getElementById(&#39;taskName&#39;).value = &quot;&quot;;
            document.getElementById(&#39;taskDeadline&#39;).value = &quot;&quot;;
            renderTasks();
        };
    }

    function addSubtask(taskId) {
        const subtaskName = document.getElementById(`subName-${taskId}`).value.trim();
        const subtaskDate = document.getElementById(`subDate-${taskId}`).value;

        if (!subtaskName || !subtaskDate) return alert(&quot;Fill in subtask description and target deadline.&quot;);

        const transaction = db.transaction([&#39;tasks&#39;], &#39;readwrite&#39;);
        const store = transaction.objectStore(&#39;tasks&#39;);

        store.get(taskId).onsuccess = function(e) {
            let task = e.target.result;
            if(!task.subtasks) task.subtasks = [];

            task.subtasks.push({
                id: Date.now(),
                name: subtaskName,
                deadline: subtaskDate,
                status: &#39;Pending&#39;,
                completionDate: &#39;&#39;
            });

            store.put(task).onsuccess = function() {
                renderTasks();
            };
        };
    }

    function changeTaskStatusInline(taskId, currentStatus) {
        let newStatus = currentStatus === &#39;Pending&#39; ? &#39;Completed&#39; : &#39;Pending&#39;;
        let compDate = &quot;&quot;;
        
        if(newStatus === &#39;Completed&#39;) {
            compDate = prompt(&quot;Confirm Completion Date (YYYY-MM-DD):&quot;, new Date().toISOString().split(&#39;T&#39;)[0]);
            if (compDate === null) return;
            if (compDate.trim() === &quot;&quot;) compDate = new Date().toISOString().split(&#39;T&#39;)[0];
        } else {
            if(!confirm(&quot;Revert main task to Pending?&quot;)) return;
        }

        const transaction = db.transaction([&#39;tasks&#39;], &#39;readwrite&#39;);
        const store = transaction.objectStore(&#39;tasks&#39;);
        store.get(taskId).onsuccess = function(e) {
            let data = e.target.result;
            data.status = newStatus;
            data.completionDate = compDate;
            store.put(data).onsuccess = function() { renderTasks(); };
        };
    }

    function changeSubtaskStatusInline(taskId, subtaskId, currentStatus) {
        let newStatus = currentStatus === &#39;Pending&#39; ? &#39;Completed&#39; : &#39;Pending&#39;;
        let compDate = &quot;&quot;;

        if(newStatus === &#39;Completed&#39;) {
            compDate = prompt(&quot;Confirm Subtask Completion Date (YYYY-MM-DD):&quot;, new Date().toISOString().split(&#39;T&#39;)[0]);
            if (compDate === null) return;
            if (compDate.trim() === &quot;&quot;) compDate = new Date().toISOString().split(&#39;T&#39;)[0];
        }

        const transaction = db.transaction([&#39;tasks&#39;], &#39;readwrite&#39;);
        const store = transaction.objectStore(&#39;tasks&#39;);
        store.get(taskId).onsuccess = function(e) {
            let task = e.target.result;
            let sub = task.subtasks.find(s =&gt; s.id === subtaskId);
            if(sub) {
                sub.status = newStatus;
                sub.completionDate = newStatus === &#39;Completed&#39; ? compDate : &quot;&quot;;
            }
            store.put(task).onsuccess = function() { renderTasks(); };
        };
    }

    function deleteTask(taskId) {
        if (!confirm(&quot;Remove this main task entirely?&quot;)) return;
        db.transaction([&#39;tasks&#39;], &#39;readwrite&#39;).objectStore(&#39;tasks&#39;).delete(taskId).onsuccess = function() {
            renderTasks();
        };
    }

    function deleteSubtask(taskId, subtaskId) {
        if (!confirm(&quot;Remove this subtask row?&quot;)) return;
        const transaction = db.transaction([&#39;tasks&#39;], &#39;readwrite&#39;);
        const store = transaction.objectStore(&#39;tasks&#39;);
        store.get(taskId).onsuccess = function(e) {
            let task = e.target.result;
            task.subtasks = task.subtasks.filter(s =&gt; s.id !== subtaskId);
            store.put(task).onsuccess = function() { renderTasks(); };
        };
    }

    function renderTasks() {
        const tbody = document.getElementById(&#39;taskTableBody&#39;);
        tbody.innerHTML = &quot;&quot;;

        const index = db.transaction([&#39;tasks&#39;], &#39;readonly&#39;).objectStore(&#39;tasks&#39;).index(&#39;projectId&#39;);
        index.getAll(IDBKeyRange.only(currentProjectId)).onsuccess = function(e) {
            let tasks = e.target.result;
            if(tasks.length === 0) {
                tbody.innerHTML = `&lt;tr&gt;&lt;td colspan=&quot;6&quot; style=&quot;text-align:center; color:#888;&quot;&gt;No tasks recorded yet.&lt;/td&gt;&lt;/tr&gt;`;
                return;
            }

            tasks.forEach(task =&gt; {
                let tr = document.createElement(&#39;tr&#39;);
                let badgeClass = task.status === &#39;Completed&#39; ? &#39;status-completed&#39; : &#39;status-pending&#39;;
                
                // Build Clean Subtask Grid layout Inside its Separate Dedicated Column
                let subtasksHtml = `&lt;div class=&quot;subtask-column-layout&quot;&gt;`;
                if(task.subtasks &amp;&amp; task.subtasks.length &gt; 0) {
                    task.subtasks.forEach(sub =&gt; {
                        let subBadge = sub.status === &#39;Completed&#39; ? &#39;status-completed&#39; : &#39;status-pending&#39;;
                        let dateDisplay = sub.completionDate ? `[Done: ${sub.completionDate}]` : &#39;&#39;;
                        subtasksHtml += `
                            &lt;div class=&quot;subtask-row&quot;&gt;
                                &lt;span style=&quot;font-weight:500; color:#495057;&quot;&gt;↳ ${sub.name}&lt;/span&gt;
                                &lt;span style=&quot;font-size:0.85em; color:#6c757d;&quot;&gt;Due: ${sub.deadline}&lt;/span&gt;
                                &lt;span class=&quot;status-badge ${subBadge}&quot; onclick=&quot;changeSubtaskStatusInline(${task.id}, ${sub.id}, &#39;${sub.status}&#39;)&quot;&gt;
                                    ${sub.status} ${dateDisplay} ⇄
                                &lt;/span&gt;
                                &lt;button style=&quot;background:none; border:none; color:var(--danger-color); cursor:pointer; font-weight:bold;&quot; onclick=&quot;deleteSubtask(${task.id}, ${sub.id})&quot; title=&quot;Delete Subtask&quot;&gt;×&lt;/button&gt;
                            &lt;/div&gt;`;
                    });
                } else {
                    subtasksHtml += `&lt;div style=&quot;font-style:italic; color:#999; font-size:0.85em; padding: 4px;&quot;&gt;No subtasks added yet.&lt;/div&gt;`;
                }
                
                // Form layout row directly inside subtask column for seamless input
                subtasksHtml += `
                    &lt;div class=&quot;subtask-input-bar&quot;&gt;
                        &lt;input type=&quot;text&quot; id=&quot;subName-${task.id}&quot; placeholder=&quot;New subtask details...&quot;&gt;
                        &lt;input type=&quot;date&quot; id=&quot;subDate-${task.id}&quot;&gt;
                        &lt;button class=&quot;btn btn-secondary&quot; style=&quot;padding:2px 10px; font-size:0.8em;&quot; onclick=&quot;addSubtask(${task.id})&quot;&gt;+ Add&lt;/button&gt;
                    &lt;/div&gt;
                &lt;/div&gt;`;

                tr.innerHTML = `
                    &lt;td&gt;&lt;strong&gt;${task.name}&lt;/strong&gt;&lt;/td&gt;
                    &lt;td&gt;${subtasksHtml}&lt;/td&gt;
                    &lt;td&gt;&lt;span style=&quot;font-size:0.9em; font-weight:500;&quot;&gt;${task.deadline}&lt;/span&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;span class=&quot;status-badge ${badgeClass}&quot; onclick=&quot;changeTaskStatusInline(${task.id}, &#39;${task.status}&#39;)&quot;&gt;${task.status} ⇄&lt;/span&gt;&lt;/td&gt;
                    &lt;td&gt;${task.completionDate ? task.completionDate : &#39;-&#39;}&lt;/td&gt;
                    &lt;td&gt;&lt;button class=&quot;btn btn-danger&quot; style=&quot;padding: 4px 8px; font-size:0.8em;&quot; onclick=&quot;deleteTask(${task.id})&quot;&gt;Delete&lt;/button&gt;&lt;/td&gt;
                `;
                tbody.appendChild(tr);
            });
        };
    }

    // --- Structured AutoTable PDF Report Outflow ---
    function exportToPDF() {
        if (!currentProjectId) return;
        const dropdown = document.getElementById(&#39;projectSelect&#39;);
        const projectName = dropdown.options[dropdown.selectedIndex].text;

        db.transaction([&#39;tasks&#39;], &#39;readonly&#39;).objectStore(&#39;tasks&#39;).index(&#39;projectId&#39;).getAll(IDBKeyRange.only(currentProjectId)).onsuccess = function(e) {
            const allTasks = e.target.result;
            const remainingTasks = allTasks.filter(t =&gt; t.status !== &#39;Completed&#39;);
            const completedTasks = allTasks.filter(t =&gt; t.status === &#39;Completed&#39;);

            const { jsPDF } = window.jspdf;
            const doc = new jsPDF();

            // Header Elements Document Style Formatting
            doc.setFont(&quot;Helvetica&quot;, &quot;bold&quot;); doc.setFontSize(18);
            doc.text(&quot;PROJECT STATUS REPORT (SEPARATED BREAKDOWN)&quot;, 14, 20);
            doc.setFontSize(11); doc.setFont(&quot;Helvetica&quot;, &quot;normal&quot;); doc.setTextColor(50);
            doc.text(`Project Workspace: ${projectName}`, 14, 28);
            doc.text(`Generated Date: ${new Date().toLocaleDateString()}`, 14, 34);
            doc.line(14, 38, 196, 38);

            let currentY = 45;

            // Section 1: Pending Matrix Rows Mapping
            doc.setFont(&quot;Helvetica&quot;, &quot;bold&quot;); doc.setFontSize(13); doc.setTextColor(220, 53, 69);
            doc.text(&quot;1. Remaining / Pending Tasks Structure&quot;, 14, currentY);

            let remainingRows = [];
            remainingTasks.forEach(t =&gt; {
                remainingRows.push([t.name, t.deadline, t.status, t.completionDate || &#39;-&#39;]);
                if(t.subtasks &amp;&amp; t.subtasks.length &gt; 0) {
                    t.subtasks.forEach(s =&gt; {
                        remainingRows.push([`   ↳ Subtask: ${s.name}`, s.deadline, `Subtask: ${s.status}`, s.completionDate || &#39;-&#39;]);
                    });
                }
            });

            window.jspdf.autoTable(doc, {
                startY: currentY + 4,
                head: [[&#39;Task / Subtask Breakdown Details&#39;, &#39;Target Deadline&#39;, &#39;Status Type&#39;, &#39;Completion Date&#39;]],
                body: remainingRows.length &gt; 0 ? remainingRows : [[&#39;No remaining workflow items found.&#39;, &#39;-&#39;, &#39;-&#39;, &#39;-&#39;]],
                headStyles: { fillColor: [220, 53, 69] },
                theme: &#39;striped&#39;,
                margin: { left: 14, right: 14 }
            });

            currentY = doc.lastAutoTable.finalY + 12;

            // Section 2: Completed Matrix Rows Mapping
            doc.setFont(&quot;Helvetica&quot;, &quot;bold&quot;); doc.setFontSize(13); doc.setTextColor(40, 167, 69);
            doc.text(&quot;2. Completed Achievements&quot;, 14, currentY);

            let completedRows = [];
            completedTasks.forEach(t =&gt; {
                completedRows.push([t.name, t.deadline, t.status, t.completionDate]);
                if(t.subtasks &amp;&amp; t.subtasks.length &gt; 0) {
                    t.subtasks.forEach(s =&gt; {
                        completedRows.push([`   ↳ Subtask: ${s.name}`, s.deadline, `Subtask: ${s.status}`, s.completionDate || &#39;-&#39;]);
                    });
                }
            });

            window.jspdf.autoTable(doc, {
                startY: currentY + 4,
                head: [[&#39;Task / Subtask Breakdown Details&#39;, &#39;Target Deadline&#39;, &#39;Status Type&#39;, &#39;Completion Date&#39;]],
                body: completedRows.length &gt; 0 ? completedRows : [[&#39;No primary achievements documented under this frame.&#39;, &#39;-&#39;, &#39;-&#39;, &#39;-&#39;]],
                headStyles: { fillColor: [40, 167, 69] },
                theme: &#39;striped&#39;,
                margin: { left: 14, right: 14 }
            });

            const sanitizedFileName = projectName.replace(/[^a-z0-9]/gi, &#39;_&#39;).toLowerCase();
            doc.save(`Subtask_Report_${sanitizedFileName}.pdf`);
        };
    }
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;
&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/06/project-tasks-report.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-6135974966372327668</guid><pubDate>Tue, 02 Jun 2026 04:47:33 +0000</pubDate><atom:updated>2026-06-23T14:05:47.174+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Design calculations</category><category domain="http://www.blogger.com/atom/ns#">Formulas</category><category domain="http://www.blogger.com/atom/ns#">Software</category><title>Fundamental Dynamics</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Fundamental Dynamics Calculator&lt;/title&gt;
    &lt;style&gt;
        :root {
            /* Maharashtra PWD / Professional Blue Theme */
            --primary: #0056b3;
            --secondary: #4a90e2;
            --bg-light: #f8f9fa;
            --border-color: #dee2e6;
            --text-dark: #212529;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, Arial, sans-serif;
            background-color: #f4f6f9;
            color: var(--text-dark);
            margin: 0;
            padding: 2px;
        }

        .container {
            max-width: 1500px;
            margin: 0 auto;
            background: #fff;
            padding: 3px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
        }

        h1 {
            color: var(--primary);
            border-bottom: 2px solid var(--primary);
            padding-bottom: 10px;
            margin-top: 0;
        }

        /* Tabs Navigation */
        .tabs {
            display: flex;
            border-bottom: 2px solid var(--border-color);
            margin-bottom: 25px;
        }

        .tab-btn {
            background: none;
            border: none;
            padding: 1px 2px;
            font-size: 16px;
            font-weight: 600;
            cursor: pointer;
            color: #6c757d;
            border-bottom: 3px solid transparent;
            transition: all 0.2s;
        }

        .tab-btn.active {
            color: var(--primary);
            border-bottom-color: var(--primary);
        }

        .tab-content {
            display: none;
        }

        .tab-content.active {
            display: block;
        }

        /* Form &amp; Grid Layout */
        .calc-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 5px;
        }

        @media (max-width: 1500px) {
            .calc-grid {
                grid-template-columns: 1fr;
            }
        }

        .card {
            background: var(--bg-light);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            padding: 2px;
        }

        .card h3 {
            margin-top: 0;
            color: var(--primary);
            border-bottom: 1px solid var(--border-color);
            padding-bottom: 2px;
        }

        .form-group {
            margin-bottom: 15px;
            display: flex;
            flex-direction: column;
        }

        label {
            font-weight: 600;
            margin-bottom: 5px;
            font-size: 14px;
        }

        input {
            padding: 2px 2px;
            border: 1px solid #ccc;
            border-radius: 4px;
            font-size: 15px;
        }

        input:focus {
            outline: none;
            border-color: var(--secondary);
            box-shadow: 0 0 5px rgba(74, 144, 226, 0.3);
        }

        /* Output Formatting */
        .results-box {
            background: #e9ecef;
            border-left: 4px solid var(--primary);
            padding: 2px;
            margin-top: 15px;
            border-radius: 0 4px 4px 0;
        }

        .result-item {
            display: flex;
            justify-content: space-between;
            padding: 2px 0;
            border-bottom: 1px dashed #ced4da;
        }

        .result-item:last-child {
            border-bottom: none;
        }

        .result-val {
            font-weight: 700;
            color: #000;
        }
      .docs-wrapper {
        max-w: 1200px;
        margin: 40px auto;
        font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif;
        color: #2d3748;
        line-height: 1.7;
        background: #ffffff;
        padding: 40px;
        border-radius: 12px;
        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
        border: 1px solid #e2e8f0;
    }
    .docs-section {
        margin-bottom: 40px;
    }
    .docs-title {
        color: #1a365d;
        font-size: 28px;
        font-weight: 700;
        border-bottom: 3px solid #3182ce;
        padding-bottom: 10px;
        margin-bottom: 20px;
    }
    .docs-subtitle {
        color: #2b6cb0;
        font-size: 20px;
        font-weight: 600;
        margin-top: 25px;
        margin-bottom: 12px;
    }
    .formula-card {
        background: #f7fafc;
        border-left: 4px solid #4299e1;
        padding: 15px 20px;
        margin: 15px 0;
        font-family: &quot;Courier New&quot;, Courier, monospace;
        font-size: 15px;
        font-weight: bold;
        color: #2d3748;
        overflow-x: auto;
    }
    .docs-grid {
        display: grid;
        grid-template-columns: 1fr;
        gap: 20px;
        margin: 20px 0;
    }
    @media (min-width: 768px) {
        .docs-grid { grid-template-columns: 1fr 1fr; }
    }
    .app-box {
        background: #ebf8ff;
        border: 1px solid #bee3f8;
        padding: 15px 20px;
        border-radius: 6px;
    }
    .app-box h4 {
        color: #2b6cb0;
        margin-top: 0;
        margin-bottom: 8px;
        font-size: 16px;
    }
    .example-table {
        width: 100%;
        border-collapse: collapse;
        margin: 15px 0;
        font-size: 14px;
    }
    .example-table th, .example-table td {
        border: 1px solid #e2e8f0;
        padding: 10px 12px;
        text-align: left;
    }
    .example-table th {
        background: #edf2f7;
        color: #4a5568;
    }
    .step-list {
        padding-left: 20px;
    }
    .step-list li {
        margin-bottom: 10px;
    }
    .text-muted {
        color: #718096;
        font-size: 13px;
    }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;container&quot;&gt;
    &lt;h1&gt;Fundamental Dynamics Calculator&lt;/h1&gt;
    
    &lt;div class=&quot;tabs&quot;&gt;
        &lt;button class=&quot;tab-btn active&quot; onclick=&quot;switchTab(&#39;kinematics&#39;)&quot;&gt;Kinematics&lt;/button&gt;
        &lt;button class=&quot;tab-btn&quot; onclick=&quot;switchTab(&#39;kinetics&#39;)&quot;&gt;Kinetics&lt;/button&gt;
    &lt;/div&gt;

    &lt;div id=&quot;kinematics&quot; class=&quot;tab-content active&quot;&gt;
        &lt;div class=&quot;calc-grid&quot;&gt;
            
            &lt;div class=&quot;card&quot;&gt;
                &lt;h3&gt;Rectilinear &amp; Fixed Axis Rotational Motion&lt;/h3&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Initial Velocity ($v_0$) [m/s] / ($\omega_0$) [rad/s]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;v0&quot; value=&quot;0&quot; oninput=&quot;calcKinematics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Constant Acceleration ($a_c$) [m/s²] / ($\alpha_c$) [rad/s²]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;ac&quot; value=&quot;2&quot; oninput=&quot;calcKinematics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Time Duration ($t$) [seconds]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;time&quot; value=&quot;5&quot; oninput=&quot;calcKinematics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Radius of Rotation ($r$) [meters] &lt;small&gt;(For Point P conversion)&lt;/small&gt;&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;rad&quot; value=&quot;0.5&quot; oninput=&quot;calcKinematics()&quot;&gt;
                &lt;/div&gt;

                &lt;div class=&quot;results-box&quot;&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Final Linear Velocity ($v$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_v&quot;&gt;0.00&lt;/span&gt; m/s&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Linear Displacement ($\Delta s$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_s&quot;&gt;0.00&lt;/span&gt; m&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Final Angular Velocity ($\omega$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_omega&quot;&gt;0.00&lt;/span&gt; rad/s&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Angular Displacement ($\theta$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_theta&quot;&gt;0.00&lt;/span&gt; rad&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Tangential Acceleration ($a_t$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_at&quot;&gt;0.00&lt;/span&gt; m/s²&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Normal Acceleration ($a_n$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_an&quot;&gt;0.00&lt;/span&gt; m/s²&lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

            &lt;div class=&quot;card&quot;&gt;
                &lt;h3&gt;Curvilinear Profiles ($n, t, b$ Geometry)&lt;/h3&gt;
                &lt;p style=&quot;font-size:13px; color:#6c757d; margin-top:-5px;&quot;&gt;Evaluates profile radius $\rho = \frac{[1 + (dy/dx)^2]^{3/2}}{|d^2y/dx^2|}$&lt;/p&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Instantaneous Velocity ($v$) [m/s]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;curv_v&quot; value=&quot;15&quot; oninput=&quot;calcKinematics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;First Derivative ($dy/dx$) [Slope]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;dydx&quot; value=&quot;0.5&quot; oninput=&quot;calcKinematics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Second Derivative ($d^2y/dx^2$) [Curvature rate]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;d2ydx2&quot; value=&quot;0.02&quot; oninput=&quot;calcKinematics()&quot;&gt;
                &lt;/div&gt;

                &lt;div class=&quot;results-box&quot; style=&quot;margin-top: 45px;&quot;&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Radius of Curvature ($\rho$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_rho&quot;&gt;0.00&lt;/span&gt; m&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Normal Acceleration ($a_n = v^2/\rho$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_curv_an&quot;&gt;0.00&lt;/span&gt; m/s²&lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div id=&quot;kinetics&quot; class=&quot;tab-content&quot;&gt;
        &lt;div class=&quot;calc-grid&quot;&gt;
            
            &lt;div class=&quot;card&quot;&gt;
                &lt;h3&gt;Mass Properties &amp; Work Parameters&lt;/h3&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Mass ($m$) [kg]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;mass&quot; value=&quot;10&quot; oninput=&quot;calcKinetics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Radius of Gyration ($k$) [meters]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;rog&quot; value=&quot;0.3&quot; oninput=&quot;calcKinetics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Constant Force ($F_c$) [Newtons]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;force&quot; value=&quot;50&quot; oninput=&quot;calcKinetics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Force Angle ($\theta$) [Degrees]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;angle&quot; value=&quot;0&quot; oninput=&quot;calcKinetics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Displacement ($\Delta s$) [meters]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;disp&quot; value=&quot;10&quot; oninput=&quot;calcKinetics()&quot;&gt;
                &lt;/div&gt;

                &lt;div class=&quot;results-box&quot;&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Mass Moment of Inertia ($I_G$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_ig&quot;&gt;0.00&lt;/span&gt; kg·m²&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Required Unopposed Force ($\Sigma F$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_f_req&quot;&gt;0.00&lt;/span&gt; N&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Work Done by Force ($U_F$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_uf&quot;&gt;0.00&lt;/span&gt; J&lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

            &lt;div class=&quot;card&quot;&gt;
                &lt;h3&gt;Energy, Power &amp; Restitution&lt;/h3&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Spring Constant ($k_s$) [N/m]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;ks&quot; value=&quot;500&quot; oninput=&quot;calcKinetics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Spring Compression/Extension ($s$) [m]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;spring_s&quot; value=&quot;0.2&quot; oninput=&quot;calcKinetics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Efficiency ($\varepsilon$) [Decimal, e.g., 0.85]&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;efficiency&quot; value=&quot;0.85&quot; min=&quot;0&quot; max=&quot;1&quot; step=&quot;0.05&quot; oninput=&quot;calcKinetics()&quot;&gt;
                &lt;/div&gt;
                &lt;div class=&quot;form-group&quot;&gt;
                    &lt;label&gt;Coefficient of Restitution ($e$)&lt;/label&gt;
                    &lt;input type=&quot;number&quot; id=&quot;cor&quot; value=&quot;0.8&quot; min=&quot;0&quot; max=&quot;1&quot; step=&quot;0.05&quot; oninput=&quot;calcKinetics()&quot;&gt;
                &lt;/div&gt;

                &lt;div class=&quot;results-box&quot; style=&quot;margin-top:25px;&quot;&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Elastic Potential Energy ($V_e$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_ve&quot;&gt;0.00&lt;/span&gt; J&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Kinetic Energy (Translational, $T$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_ke&quot;&gt;0.00&lt;/span&gt; J&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Useful Power Output ($P_{\text{out}}$ @ $v_o$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_pout&quot;&gt;0.00&lt;/span&gt; W&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Required Power Input ($P_{\text{in}}$):&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_pin&quot;&gt;0.00&lt;/span&gt; W&lt;/div&gt;
                    &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Relative Separation Velocity:&lt;/span&gt; &lt;span class=&quot;result-val&quot; id=&quot;res_vsep&quot;&gt;0.00&lt;/span&gt; m/s&lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
  
  &lt;div class=&quot;docs-wrapper&quot;&gt;
    &lt;section class=&quot;docs-section&quot;&gt;
        &lt;h2 class=&quot;docs-title&quot;&gt;Theoretical Framework: Kinematics vs. Kinetics in Classical Mechanics&lt;/h2&gt;
        &lt;p&gt;
            In engineering design and analytical mechanics, analyzing moving systems requires dividing problems into two fundamental classifications: &lt;strong&gt;Kinematics&lt;/strong&gt; and &lt;strong&gt;Kinetics&lt;/strong&gt;. While both frameworks examine motion parameters across spatial coordinates, their mathematical boundaries evaluate entirely separate conditions. 
        &lt;/p&gt;
        &lt;p&gt;
            &lt;strong&gt;Kinematics&lt;/strong&gt; acts as the geometry of motion. It details, maps, and analyzes the position, velocity, acceleration, and temporal profiles of particles or rigid bodies without accounting for the active structural forces, torques, or masses that induce the change in state. Conversely, &lt;strong&gt;Kinetics&lt;/strong&gt; forms the causal bridge, connecting the geometric displacement pathways derived via kinematics directly to the unbalanced forces, system mass properties, work expenditures, and energy transfers governed by Newtonian laws.
        &lt;/p&gt;

        &lt;h3 class=&quot;docs-subtitle&quot;&gt;1. Rectilinear Tracking &amp;amp; Fixed-Axis Rotational Analogies&lt;/h3&gt;
        &lt;p&gt;
            When processing particle dynamics along a direct one-dimensional spatial path, a constant linear acceleration profile allows for direct algebraic integrations over a fixed time frame. Similarly, rigid bodies rotating about a stationary axis of rotation mirror these exact expressions when mapped through angular transformations. The structural parallels are defined as follows:
        &lt;/p&gt;
        &lt;div class=&quot;formula-card&quot;&gt;
            Linear Velocity: v = v₀ + (a_c × t)&lt;br&gt;
            Linear Displacement: Δs = (v₀ × t) + (0.5 × a_c × t²)&lt;br&gt;&lt;br&gt;
            Angular Velocity: ω = ω₀ + (α_c × t)&lt;br&gt;
            Angular Displacement: θ = (ω₀ × t) + (0.5 × α_c × t²)
        &lt;/div&gt;
        &lt;p&gt;
            When tracking a specific point (Point P) located along a rotating structural element at a radial distance (r) from the center of rotation, the point experiences a split acceleration profile. The &lt;strong&gt;Tangential Acceleration (a&lt;sub&gt;t&lt;/sub&gt;)&lt;/strong&gt; accounts for changes in speed and maps directly to the angular acceleration, while the &lt;strong&gt;Normal Acceleration (a&lt;sub&gt;n&lt;/sub&gt;)&lt;/strong&gt; represents the continuous change in spatial direction caused by centripetal forces pushing inward toward the axis.
        &lt;/p&gt;
        &lt;div class=&quot;formula-card&quot;&gt;
            a&lt;sub&gt;t&lt;/sub&gt; = α_c × r &amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp; a&lt;sub&gt;n&lt;/sub&gt; = ω² × r
        &lt;/div&gt;

        &lt;h3 class=&quot;docs-subtitle&quot;&gt;2. Curvilinear Coordinate Profiles (Normal-Tangential Plane Geometry)&lt;/h3&gt;
        &lt;p&gt;
            For complex trajectories—such as calculating safety clear zones along highway horizontal curves or tracking mechanical structural fairings—particles are analyzed using localized Normal-Tangential (n-t) coordinate systems. If the continuous path profile is represented analytically by a spatial function y = f(x), the instantaneous local tracking radius can be determined using calculus via the &lt;strong&gt;Radius of Curvature (ρ)&lt;/strong&gt; formula:
        &lt;/p&gt;
        &lt;div class=&quot;formula-card&quot;&gt;
            ρ = [1 + (dy/dx)²]&lt;sup&gt;1.5&lt;/sup&gt; / |d²y/dx²|&lt;br&gt;
            a&lt;sub&gt;n&lt;/sub&gt; = v² / ρ
        &lt;/div&gt;
        &lt;p&gt;
            Here, dy/dx defines the instantaneous linear slope parameter, while d²y/dx² evaluates the curvature rate. A high curvature rate dramatically compresses the local radius ρ, causing a sharp spike in normal acceleration forces even when vehicle or equipment velocity remains completely static.
        &lt;/p&gt;

        &lt;h3 class=&quot;docs-subtitle&quot;&gt;3. Mass Profile Sizing &amp;amp; The Work-Energy Theorem&lt;/h3&gt;
        &lt;p&gt;
            Moving from geometric tracking to kinetic analysis requires mapping the resistance to motion. In linear translation, this parameter is system mass (m). In rotational systems, resistance to angular acceleration depends on how that mass is distributed relative to the axis of rotation—defined as the &lt;strong&gt;Mass Moment of Inertia (I&lt;sub&gt;G&lt;/sub&gt;)&lt;/strong&gt;. Engineers simplify this structural distribution property using the &lt;strong&gt;Radius of Gyration (k)&lt;/strong&gt;:
        &lt;/p&gt;
        &lt;div class=&quot;formula-card&quot;&gt;
            I&lt;sub&gt;G&lt;/sub&gt; = m × k²
        &lt;/div&gt;
        &lt;p&gt;
            When external force fields interact with these components, the total change in kinetic state matches the net work executed on the system. If a constant external force (F&lt;sub&gt;c&lt;/sub&gt;) acts at an angular offset (θ) across a linear translation path (Δs), the work parameter (U_F) and required unopposed balancing force are governed by:
        &lt;/p&gt;
        &lt;div class=&quot;formula-card&quot;&gt;
            U_F = F_c × cos(θ) × Δs &amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp; ΣF = m × a_c
        &lt;/div&gt;

        &lt;h3 class=&quot;docs-subtitle&quot;&gt;4. Energy Transformations, Spring Metrics, and Collisions&lt;/h3&gt;
        &lt;p&gt;
            In closed system evaluations, mechanical energy transfers continuously between kinetic configurations (T = 0.5 × m × v²) and potential storage configurations. Elastic recovery devices (such as mechanical isolation springs or structural dampening columns) store energy in the form of &lt;strong&gt;Elastic Potential Energy (V&lt;sub&gt;e&lt;/sub&gt;)&lt;/strong&gt; based on their spring stiffness constant (k&lt;sub&gt;s&lt;/sub&gt;) and deformation distance (s):
        &lt;/p&gt;
        &lt;div class=&quot;formula-card&quot;&gt;
            V&lt;sub&gt;e&lt;/sub&gt; = 0.5 × k&lt;sub&gt;s&lt;/sub&gt; × s²
        &lt;/div&gt;
        &lt;p&gt;
            Real-world transfers are bounded by mechanical system operating efficiencies (ε). The real power input required to drive a system demands more energy expenditure than the useful power output delivered. Additionally, sudden velocity changes due to impacts are governed by the &lt;strong&gt;Coefficient of Restitution (e)&lt;/strong&gt;, a localized material index dictating relative separation speeds relative to initial approach parameters:
        &lt;/p&gt;
        &lt;div class=&quot;formula-card&quot;&gt;
            P&lt;sub&gt;out&lt;/sub&gt; = (F_c × cos(θ)) × v₀ &amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp; P&lt;sub&gt;in&lt;/sub&gt; = P&lt;sub&gt;out&lt;/sub&gt; / ε &amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp; v&lt;sub&gt;sep&lt;/sub&gt; = e × v
        &lt;/div&gt;

        &lt;div class=&quot;docs-grid&quot;&gt;
            &lt;div class=&quot;app-box&quot;&gt;
                &lt;h4&gt;Civil Infrastructure Applications&lt;/h4&gt;
                &lt;p class=&quot;text-muted&quot;&gt;Used to check structural safe banking angles, maximum approach speed limits on horizontal transitions, and kinetic energy absorption profiles for highway crash cushions.&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class=&quot;app-box&quot;&gt;
                &lt;h4&gt;Mechanical Sizing Applications&lt;/h4&gt;
                &lt;p class=&quot;text-muted&quot;&gt;Used to calculate the required power inputs for industrial cranes, torque load limits on rotating shafts, and the spring constants needed for heavy equipment vibration isolators.&lt;/p&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/section&gt;

    &lt;section class=&quot;docs-section&quot; style=&quot;border-top: 1px solid #e2e8f0; padding-top: 20px;&quot;&gt;
        &lt;h2 class=&quot;docs-title&quot;&gt;Operational Manual &amp;amp; Verification Guide&lt;/h2&gt;
        &lt;p&gt;
            The Fundamental Dynamics Calculator processes system parameters in real time. Follow these steps to navigate modules and process engineering scenarios:
        &lt;/p&gt;
        
        &lt;h3 class=&quot;docs-subtitle&quot;&gt;How to Operate the Interface&lt;/h3&gt;
        &lt;ol class=&quot;step-list&quot;&gt;
            &lt;li&gt;&lt;strong&gt;Select Core Domain:&lt;/strong&gt; Click the &lt;strong&gt;Kinematics&lt;/strong&gt; tab to calculate pure motion values (velocities, curves, coordinates). Click the &lt;strong&gt;Kinetics&lt;/strong&gt; tab to evaluate mechanical properties (forces, inertia, spring metrics, power calculations).&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Provide Inputs:&lt;/strong&gt; Click inside any numeric field and type your engineering parameters. The script recalculates values immediately upon input change; there is no need to click a submit button.&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Interpret Output Fields:&lt;/strong&gt; Results update in real time in the gray boxes at the bottom of each card. Units match standard SI metrics (meters, seconds, Newtons, Joules, Watts).&lt;/li&gt;
        &lt;/ol&gt;

        &lt;h3 class=&quot;docs-subtitle&quot;&gt;Mathematical Benchmark Verification Case&lt;/h3&gt;
        &lt;p&gt;
            To verify system calculations, enter the following default parameter baseline into the calculator engine and check the outputs against the analytical solutions below:
        &lt;/p&gt;

        &lt;table class=&quot;example-table&quot;&gt;
            &lt;thead&gt;
                &lt;tr&gt;
                    &lt;th&gt;Module Category&lt;/th&gt;
                    &lt;th&gt;Input Parameters Entered&lt;/th&gt;
                    &lt;th&gt;Expected Analytical Output Value&lt;/th&gt;
                    &lt;th&gt;Governing Formula Applied&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr&gt;
                    &lt;td&gt;&lt;strong&gt;Rectilinear Kinematics&lt;/strong&gt;&lt;/td&gt;
                    &lt;td&gt;v₀ = 0 m/s, a&lt;sub&gt;c&lt;/sub&gt; = 2 m/s², t = 5 s&lt;/td&gt;
                    &lt;td&gt;&lt;strong&gt;Final Velocity (v):&lt;/strong&gt; 10.00 m/s&lt;/td&gt;
                    &lt;td&gt;v = v₀ + a&lt;sub&gt;c&lt;/sub&gt;t = 0 + 2(5)&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td&gt;&lt;strong&gt;Linear Displacement&lt;/strong&gt;&lt;/td&gt;
                    &lt;td&gt;v₀ = 0 m/s, a&lt;sub&gt;c&lt;/sub&gt; = 2 m/s², t = 5 s&lt;/td&gt;
                    &lt;td&gt;&lt;strong&gt;Displacement (Δs):&lt;/strong&gt; 25.00 m&lt;/td&gt;
                    &lt;td&gt;Δs = v₀t + 0.5a&lt;sub&gt;c&lt;/sub&gt;t² = 0 + 0.5(2)(25)&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td&gt;&lt;strong&gt;Point P Transformation&lt;/strong&gt;&lt;/td&gt;
                    &lt;td&gt;r = 0.5 m, (Calculated ω = 10.00 rad/s)&lt;/td&gt;
                    &lt;td&gt;&lt;strong&gt;Normal Accel. (a&lt;sub&gt;n&lt;/sub&gt;):&lt;/strong&gt; 50.00 m/s²&lt;/td&gt;
                    &lt;td&gt;a&lt;sub&gt;n&lt;/sub&gt; = ω²r = (10)² × 0.5 = 100 × 0.5&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td&gt;&lt;strong&gt;Curvilinear Geometry&lt;/strong&gt;&lt;/td&gt;
                    &lt;td&gt;v = 15 m/s, dy/dx = 0.5, d²y/dx² = 0.02&lt;/td&gt;
                    &lt;td&gt;&lt;strong&gt;Radius of Curvature (ρ):&lt;/strong&gt; 69.88 m&lt;/td&gt;
                    &lt;td&gt;ρ = [1 + (0.5)²]&lt;sup&gt;1.5&lt;/sup&gt; / 0.02 = 1.3975 / 0.02&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td&gt;&lt;strong&gt;Mass &amp;amp; Inertia Sizing&lt;/strong&gt;&lt;/td&gt;
                    &lt;td&gt;m = 10 kg, Radius of Gyration k = 0.3 m&lt;/td&gt;
                    &lt;td&gt;&lt;strong&gt;Inertia (I&lt;sub&gt;G&lt;/sub&gt;):&lt;/strong&gt; 0.9000 kg·m²&lt;/td&gt;
                    &lt;td&gt;I&lt;sub&gt;G&lt;/sub&gt; = m × k² = 10 × (0.3)² = 10 × 0.09&lt;/td&gt;
                &lt;/tr&gt;
                &lt;tr&gt;
                    &lt;td&gt;&lt;strong&gt;Work &amp;amp; Energy Profiles&lt;/strong&gt;&lt;/td&gt;
                    &lt;td&gt;Spring Constant k&lt;sub&gt;s&lt;/sub&gt; = 500 N/m, s = 0.2 m&lt;/td&gt;
                    &lt;td&gt;&lt;strong&gt;Potential Energy (V&lt;sub&gt;e&lt;/sub&gt;):&lt;/strong&gt; 10.00 J&lt;/td&gt;
                    &lt;td&gt;V&lt;sub&gt;e&lt;/sub&gt; = 0.5 × k&lt;sub&gt;s&lt;/sub&gt; × s² = 0.5 × 500 × 0.04&lt;/td&gt;
                &lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
        &lt;p class=&quot;text-muted&quot; style=&quot;font-style: italic;&quot;&gt;
            Note: The Kinetics module uses the calculated results from the Kinematics tab as live context parameters. Modifying velocity or acceleration fields inside the Kinematics tab will cause corresponding updates to Kinetic energy, power required, and impact velocity outputs automatically.
        &lt;/p&gt;
    &lt;/section&gt;
&lt;/div&gt;

&lt;script&gt;
    // Tab Switcher Logic
    function switchTab(tabId) {
        document.querySelectorAll(&#39;.tab-content&#39;).forEach(el =&gt; el.classList.remove(&#39;active&#39;));
        document.querySelectorAll(&#39;.tab-btn&#39;).forEach(el =&gt; el.classList.remove(&#39;active&#39;));
        
        document.getElementById(tabId).classList.add(&#39;active&#39;);
        event.currentTarget.classList.add(&#39;active&#39;);
        
        // Refresh calculations on view change
        calcKinematics();
        calcKinetics();
    }

    // Kinematics Calculation Block
    function calcKinematics() {
        // Inputs
        const v0 = parseFloat(document.getElementById(&#39;v0&#39;).value) || 0;
        const ac = parseFloat(document.getElementById(&#39;ac&#39;).value) || 0;
        const t = parseFloat(document.getElementById(&#39;time&#39;).value) || 0;
        const r = parseFloat(document.getElementById(&#39;rad&#39;).value) || 0;
        
        const curv_v = parseFloat(document.getElementById(&#39;curv_v&#39;).value) || 0;
        const dydx = parseFloat(document.getElementById(&#39;dydx&#39;).value) || 0;
        const d2ydx2 = Math.abs(parseFloat(document.getElementById(&#39;d2ydx2&#39;).value)) || 0.00001; // Avoid divide by zero

        // 1. Rectilinear Calculations
        const v = v0 + (ac * t);
        const s = (v0 * t) + (0.5 * ac * t * t);

        // 2. Fixed Axis Rotational Calculations (Direct mappings match setup formulas)
        const omega = v0 + (ac * t); 
        const theta = (v0 * t) + (0.5 * ac * t * t);

        // 3. Point P Transformations
        const at = ac * r;
        const an = (omega * omega) * r;

        // 4. Curvilinear Geometry Equations
        const rho = Math.pow(1 + Math.pow(dydx, 2), 1.5) / d2ydx2;
        const curv_an = (curv_v * curv_v) / rho;

        // Render Outputs
        document.getElementById(&#39;res_v&#39;).innerText = v.toFixed(2);
        document.getElementById(&#39;res_s&#39;).innerText = s.toFixed(2);
        document.getElementById(&#39;res_omega&#39;).innerText = omega.toFixed(2);
        document.getElementById(&#39;res_theta&#39;).innerText = theta.toFixed(2);
        document.getElementById(&#39;res_at&#39;).innerText = at.toFixed(2);
        document.getElementById(&#39;res_an&#39;).innerText = an.toFixed(2);
        document.getElementById(&#39;res_rho&#39;).innerText = rho.toFixed(2);
        document.getElementById(&#39;res_curv_an&#39;).innerText = curv_an.toFixed(2);
    }

    // Kinetics Calculation Block
    function calcKinetics() {
        // Inputs
        const m = parseFloat(document.getElementById(&#39;mass&#39;).value) || 0;
        const k = parseFloat(document.getElementById(&#39;rog&#39;).value) || 0;
        const Fc = parseFloat(document.getElementById(&#39;force&#39;).value) || 0;
        const angleDeg = parseFloat(document.getElementById(&#39;angle&#39;).value) || 0;
        const ds = parseFloat(document.getElementById(&#39;disp&#39;).value) || 0;
        
        const ks = parseFloat(document.getElementById(&#39;ks&#39;).value) || 0;
        const spring_s = parseFloat(document.getElementById(&#39;spring_s&#39;).value) || 0;
        const eff = parseFloat(document.getElementById(&#39;efficiency&#39;).value) || 1;
        const cor = parseFloat(document.getElementById(&#39;cor&#39;).value) || 0;
        
        // Grab context from Kinematics outputs dynamically
        const current_v = parseFloat(document.getElementById(&#39;res_v&#39;).innerText) || 0;
        const current_v0 = parseFloat(document.getElementById(&#39;v0&#39;).value) || 0;
        const ac_val = parseFloat(document.getElementById(&#39;ac&#39;).value) || 0;

        // 1. Mass Profile
        const Ig = m * (k * k);

        // 2. Force &amp; Work
        const angleRad = angleDeg * (Math.PI / 180);
        const U_F = Fc * Math.cos(angleRad) * ds;
        const F_req = m * ac_val; // Required force for specified linear acceleration

        // 3. Energy Metrics
        const Ve = 0.5 * ks * (spring_s * spring_s);
        const KE = 0.5 * m * (current_v * current_v);

        // 4. Power &amp; Efficiency Profile
        // P = F * v (Using horizontal force component at execution velocity)
        const P_out = (Fc * Math.cos(angleRad)) * current_v0; 
        const P_in = eff &gt; 0 ? (P_out / eff) : 0;

        // 5. Momentum Collision Check
        // e = v_sep / v_appr -&gt; Relative separation speed across a boundary plane
        const v_sep = cor * current_v;

        // Render Outputs
        document.getElementById(&#39;res_ig&#39;).innerText = Ig.toFixed(4);
        document.getElementById(&#39;res_f_req&#39;).innerText = F_req.toFixed(2);
        document.getElementById(&#39;res_uf&#39;).innerText = U_F.toFixed(2);
        document.getElementById(&#39;res_ve&#39;).innerText = Ve.toFixed(2);
        document.getElementById(&#39;res_ke&#39;).innerText = KE.toFixed(2);
        document.getElementById(&#39;res_pout&#39;).innerText = P_out.toFixed(2);
        document.getElementById(&#39;res_pin&#39;).innerText = P_in.toFixed(2);
        document.getElementById(&#39;res_vsep&#39;).innerText = v_sep.toFixed(2);
    }

    // Run initial execution loops on initialization
    window.onload = function() {
        calcKinematics();
        calcKinetics();
    };
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;
&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/06/fundamental-dynamics.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-1431075268105714920</guid><pubDate>Thu, 28 May 2026 06:02:03 +0000</pubDate><atom:updated>2026-06-22T19:22:36.554+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Bridge</category><category domain="http://www.blogger.com/atom/ns#">Building</category><category domain="http://www.blogger.com/atom/ns#">Design calculations</category><category domain="http://www.blogger.com/atom/ns#">Earth retaining structures</category><category domain="http://www.blogger.com/atom/ns#">Structural Analysis</category><title>Tool for analysis of Isolated footing subjected to axial load and high biaxial moments</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
  
    &lt;title&gt;Rigorous 5-Case Biaxial Footing Analyzer &amp; Report Generator&lt;/title&gt;
&lt;style&gt;
    /* ==========================================
       GLOBAL APP WRAPPER &amp; RESET FOR BLOGGER
       ========================================== */
    .app-viewport-wrapper {
        box-sizing: border-box;
        width: 100%;
        font-family: &#39;Segoe UI&#39;, -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
        line-height: 1.5;
        margin: 15px auto;
        padding: 0;
    }
    
    .app-viewport-wrapper *, 
    .app-viewport-wrapper *:before, 
    .app-viewport-wrapper *:after {
        box-sizing: inherit;
    }

    /* ==========================================
       SCREEN ARCHITECTURE (DARK APPLICATION UI)
       ========================================== */
    .app-container {
        max-width: 100%; /* Ensures it never overflows the Blogger post column */
        width: 1400px;
        margin: 0 auto;
        background: #1e293b;
        color: #f8fafc;
        border-radius: 12px;
        box-shadow: 0 10px 25px rgba(0,0,0,0.25);
        padding: 25px;
    }
    
    .app-container header {
        background: linear-gradient(135deg, #0f172a 0%, #111827 100%);
        color: #ffffff;
        padding: 25px;
        border-radius: 8px;
        margin-bottom: 25px;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }
    
    .app-container h1 { 
        color: #38bdf8; 
        font-size: 24px; 
        text-transform: uppercase; 
        margin: 0 0 5px 0; 
        border-bottom: 2px solid #475569; 
        padding-bottom: 10px;
    }
    
    .app-container h2 { 
        color: #f1f5f9; 
        font-size: 16px; 
        margin: 20px 0 10px 0; 
        border-left: 4px solid #38bdf8; 
        padding-left: 8px;
        border-bottom: none;
        padding-bottom: 0;
    }
    
    .app-container h3 { 
        color: #38bdf8; 
        margin-top: 20px; 
        font-size: 16px;
    }

    /* Interactive Layout Grid */
    .main-grid {
        display: grid;
        grid-template-columns: 1fr 1.3fr;
        gap: 25px;
    }
    
    @media (max-width: 900px) {
        .main-grid {
            grid-template-columns: 1fr; /* Responsive fallback for phones/tablets */
        }
    }

    /* Cards &amp; Inputs */
    .input-card {
        background: #334155;
        padding: 20px;
        border-radius: 8px;
        border: 1px solid #475569;
    }
    
    .app-container label { 
        display: block; 
        font-size: 13px; 
        font-weight: 600; 
        margin-top: 12px; 
        color: #cbd5e1; 
    }
    
    .app-container input { 
        width: 100%; 
        padding: 10px; 
        margin: 5px 0 12px 0; 
        background: #1e293b; 
        border: 1px solid #475569; 
        border-radius: 6px; 
        color: #ffffff; 
    }
    
    .app-container input:focus {
        outline: 2px solid #0ea5e9;
        border-color: transparent;
    }

    /* Dynamic Buttons */
    .btn { 
        width: 100%; 
        padding: 12px; 
        font-weight: bold; 
        border-radius: 6px; 
        cursor: pointer; 
        border: none; 
        transition: background 0.2s ease-in-out; 
        margin-bottom: 10px; 
        font-size: 14px; 
    }
    .btn-calc { background: #0284c7; color: #ffffff; }
    .btn-calc:hover { background: #0369a1; }
    .btn-pdf { background: #ef4444; color: #ffffff; }
    .btn-pdf:hover { background: #dc2626; }
    
    /* Interactive View Tables */
    .app-container table { 
        width: 100%; 
        border-collapse: collapse; 
        margin: 15px 0; 
        font-size: 13px; 
        background: #1e293b; 
        border-radius: 6px;
        overflow: hidden;
        box-shadow: none;
    }
    .app-container th, .app-container td { 
        border: 1px solid #475569; 
        padding: 10px 12px; 
        text-align: left; 
    }
    .app-container th { 
        background: #0f172a; 
        color: #38bdf8; 
        font-weight: 600;
    }
    .app-container td { color: #f8fafc; }

    /* Component Badges */
    .badge { background: #0ea5e9; padding: 3px 8px; border-radius: 4px; font-weight: bold; font-family: monospace; color: white;}
    .badge-alert { background: #f59e0b; }
    .badge-crit { background: #ef4444; }
    
    canvas { 
        background: #ffffff; 
        border-radius: 8px; 
        border: 1px solid #475569;
        width: 100%; 
        height: auto; 
        margin-top: 15px; 
        display: block;
    }
    
    code {
        font-family: &quot;SFMono-Regular&quot;, Consolas, &quot;Liberation Mono&quot;, Menlo, monospace;
        background-color: #f1f5f9;
        padding: 2px 6px;
        border-radius: 4px;
        font-size: 0.9em;
        color: #0f172a;
    }

    /* ==========================================
       TECHNICAL DOCUMENT / USER GUIDE VIEW (LIGHT INTERFACE)
       ========================================== */
    .guide-container {
        background: #ffffff;
        color: #334155;
        border: 1px solid #e2e8f0;
        border-radius: 12px;
        padding: 30px;
        margin-top: 30px;
        box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05);
    }
    .guide-container h2 {
        color: #0f172a; 
        font-size: 20px;
        border-bottom: 2px solid #e2e8f0; 
        padding-bottom: 8px; 
        margin-top: 35px;
    }
    .guide-container h3 { color: #0284c7; margin-top: 25px; font-size: 16px; }
    .guide-container table {
        width: 100%;
        border-collapse: collapse;
        margin: 20px 0;
        background: #ffffff;
        border-radius: 8px;
        overflow: hidden;
        border: 1px solid #e2e8f0;
    }
    .guide-container th, .guide-container td {
        padding: 12px 15px;
        text-align: left;
        border-bottom: 1px solid #e2e8f0;
        color: #334155;
    }
    .guide-container th { background-color: #f1f5f9; color: #1e293b; font-weight: 600; border: none; }
    .guide-container ul { padding-left: 20px; }
    .guide-container li { margin-bottom: 8px; }
    
    /* Technical Alert Containers */
    .alert-box {
        background-color: #fff1f2;
        border-left: 4px solid #f43f5e;
        padding: 15px;
        border-radius: 0 8px 8px 0;
        margin: 20px 0;
        color: #9f1239;
    }
    .info-box {
        background-color: #f0fdf4;
        border-left: 4px solid #22c55e;
        padding: 15px;
        border-radius: 0 8px 8px 0;
        margin: 20px 0;
        color: #166534;
    }
    .case-card {
        background: #f8fafc;
        border: 1px solid #e2e8f0;
        border-radius: 8px;
        padding: 20px;
        margin-bottom: 15px;
    }

    /* Hidden cleanly on workspace UI screen views */
    #pdfReportLayout { display: none; }

    /* ==========================================
       STRICT PRINT STYLESHEET (PDF EXPORT ENGINE)
       ========================================== */
    @media print {
        @page {
            size: A4 portrait;
            margin: 20mm 15mm 20mm 15mm;
        }
        body {
            background: #ffffff !important;
            color: #0f172a !important;
            font-family: &#39;Segoe UI&#39;, Arial, sans-serif !important;
            font-size: 11pt !important;
            padding: 0 !important;
            margin: 0 !important;
        }
        .app-viewport-wrapper, .app-container, .guide-container, .no-print, canvas {
            display: none !important; 
        }
        #pdfReportLayout {
            display: block !important; 
        }
        .pdf-header {
            border-bottom: 3px solid #1e3a8a;
            padding-bottom: 5px;
            margin-bottom: 20px;
        }
        .pdf-header h1 {
            color: #1e3a8a !important;
            font-size: 24pt !important;
            margin: 0 !important;
            border: none !important;
        }
        #pdfReportLayout h2 {
            color: #1e40af !important;
            font-size: 14pt !important;
            margin: 20px 0 8px 0 !important;
            border-left: 4px solid #1e40af !important;
            padding-left: 6px !important;
            border-bottom: none !important;
            page-break-after: avoid !important;
        }
        #pdfReportLayout table {
            width: 100% !important;
            margin: 12px 0 !important;
            background: transparent !important;
            page-break-inside: avoid !important;
            border-collapse: collapse !important;
        }
        #pdfReportLayout th {
            background-color: #1e3a8a !important;
            color: white !important;
            font-weight: 600 !important;
            -webkit-print-color-adjust: exact;
            print-color-adjust: exact;
        }
        #pdfReportLayout td, #pdfReportLayout th {
            border: 1px solid #cbd5e1 !important;
            padding: 8px 10px !important;
            color: #0f172a !important;
            font-size: 10pt !important;
        }
        #pdfReportLayout tr:nth-child(even) {
            background-color: #f8fafc !important;
            -webkit-print-color-adjust: exact;
            print-color-adjust: exact;
        }
        .pdf-diagram {
            text-align: center;
            margin: 20px 0;
            page-break-inside: avoid;
        }
        .pdf-diagram img {
            max-width: 80%;
            border: 1px solid #94a3b8;
            border-radius: 6px;
        }
        .case-banner {
            background: #fef3c7 !important;
            border-left: 5px solid #d97706 !important;
            padding: 12px;
            margin: 15px 0;
            color: #78350f !important;
            -webkit-print-color-adjust: exact;
            print-color-adjust: exact;
        }
        .sign-row {
            margin-top: 50px;
            page-break-inside: avoid;
        }
    }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;app-container&quot;&gt;

    &lt;h1&gt;
        Rigorous Biaxial Footing Analyzer
        (All 5 Analytical Cases)
    &lt;/h1&gt;

    &lt;div class=&quot;main-grid&quot;&gt;

        &lt;!-- ===================================== --&gt;
        &lt;!-- INPUT PANEL --&gt;
        &lt;!-- ===================================== --&gt;

        &lt;div class=&quot;input-card no-print&quot;&gt;

            &lt;h2&gt;Design Load Inputs &amp; Geometry&lt;/h2&gt;

            &lt;label for=&quot;L&quot;&gt;
                Footing Length L (m)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;L&quot;
                value=&quot;3.00&quot;
                step=&quot;0.05&quot;
                min=&quot;0.01&quot;
            &gt;

            &lt;label for=&quot;B&quot;&gt;
                Footing Width B (m)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;B&quot;
                value=&quot;2.50&quot;
                step=&quot;0.05&quot;
                min=&quot;0.01&quot;
            &gt;

            &lt;label for=&quot;P&quot;&gt;
                Axial Structural Load P (kN)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;P&quot;
                value=&quot;1500&quot;
                step=&quot;25&quot;
                min=&quot;0.01&quot;
            &gt;

            &lt;label for=&quot;Mx&quot;&gt;
                Moment Mx (kNm, about X-Axis)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;Mx&quot;
                value=&quot;650&quot;
                step=&quot;10&quot;
            &gt;

            &lt;label for=&quot;My&quot;&gt;
                Moment My (kNm, about Y-Axis)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;My&quot;
                value=&quot;550&quot;
                step=&quot;10&quot;
            &gt;

            &lt;!-- ===================================== --&gt;
            &lt;!-- GEOTECHNICAL PARAMETERS --&gt;
            &lt;!-- ===================================== --&gt;

            &lt;h2&gt;Geotechnical &amp; Stability Parameters&lt;/h2&gt;

            &lt;label for=&quot;qall&quot;&gt;
                Allowable SBC q&lt;sub&gt;all&lt;/sub&gt; (kN/m²)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;qall&quot;
                value=&quot;250&quot;
                step=&quot;5&quot;
                min=&quot;1&quot;
            &gt;

            &lt;label for=&quot;mu&quot;&gt;
                Coefficient of Friction μ
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;mu&quot;
                value=&quot;0.50&quot;
                step=&quot;0.05&quot;
                min=&quot;0&quot;
            &gt;

            &lt;label for=&quot;H&quot;&gt;
                Factored Horizontal Load H (kN)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;H&quot;
                value=&quot;120&quot;
                step=&quot;5&quot;
                min=&quot;0&quot;
            &gt;

            &lt;label for=&quot;t&quot;&gt;
                Footing Thickness t (m)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;t&quot;
                value=&quot;0.75&quot;
                step=&quot;0.05&quot;
                min=&quot;0.05&quot;
            &gt;

            &lt;label for=&quot;cx&quot;&gt;
                Column Size Along X (m)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;cx&quot;
                value=&quot;0.50&quot;
                step=&quot;0.05&quot;
                min=&quot;0.05&quot;
            &gt;

            &lt;label for=&quot;cy&quot;&gt;
                Column Size Along Y (m)
            &lt;/label&gt;
            &lt;input
                type=&quot;number&quot;
                id=&quot;cy&quot;
                value=&quot;0.50&quot;
                step=&quot;0.05&quot;
                min=&quot;0.05&quot;
            &gt;

            &lt;!-- ===================================== --&gt;
            &lt;!-- ACTION BUTTONS --&gt;
            &lt;!-- ===================================== --&gt;

            &lt;button
                class=&quot;btn btn-calc&quot;
                onclick=&quot;evaluateFootingMechanics()&quot;
                type=&quot;button&quot;
            &gt;
                Compute Metrics
            &lt;/button&gt;

            &lt;button
                class=&quot;btn btn-pdf&quot;
                onclick=&quot;generateProfessionalReportPDF()&quot;
                type=&quot;button&quot;
            &gt;
                📄 Export Calculation PDF
            &lt;/button&gt;

        &lt;/div&gt;
      &lt;/div&gt;

        &lt;!-- ===================================== --&gt;
        &lt;!-- RESULTS PANEL --&gt;
        &lt;!-- ===================================== --&gt;

        &lt;div&gt;

            &lt;div
                class=&quot;input-card&quot;
                style=&quot;background:#1e293b;&quot;
            &gt;

                &lt;h2&gt;
                    Current Execution Matrix Preview
                &lt;/h2&gt;

                &lt;div id=&quot;screenReadout&quot;&gt;
                    Run computation to verify active stress blocks.
                &lt;/div&gt;

            &lt;/div&gt;

            &lt;canvas
                id=&quot;blueprintCanvas&quot;
                width=&quot;600&quot;
                height=&quot;500&quot;
            &gt;&lt;/canvas&gt;

        &lt;/div&gt;

    &lt;/div&gt;

&lt;!-- ===================================== --&gt;
&lt;!-- PDF REPORT LAYOUT --&gt;
&lt;!-- ===================================== --&gt;

&lt;div id=&quot;pdfReportLayout&quot;&gt;

    &lt;!-- HEADER --&gt;

    &lt;div class=&quot;pdf-header&quot;&gt;

        &lt;h1&gt;
            Structural Engineering Calculation Document
        &lt;/h1&gt;

        &lt;div
            style=&quot;
                font-size:10pt;
                color:#475569;
                font-weight:bold;
            &quot;
        &gt;
            RIGID SHALLOW FOOTING BIAXIAL
            PRESSURE REPORT
            (ALL 5 GEOMETRIC CASES)
        &lt;/div&gt;

    &lt;/div&gt;

    &lt;p&gt;
        &lt;strong&gt;Generation Date:&lt;/strong&gt;
        &lt;span id=&quot;pdfTime&quot;&gt;&lt;/span&gt;
    &lt;/p&gt;

    &lt;!-- SECTION 1 --&gt;

    &lt;h2&gt;
        1. Input Geometric Bounds &amp; Vector Loading
    &lt;/h2&gt;

    &lt;div id=&quot;pdfInputsTable&quot;&gt;&lt;/div&gt;

    &lt;!-- SECTION 2 --&gt;

    &lt;h2&gt;
        2. Stress Block Case Evaluation Framework
    &lt;/h2&gt;

    &lt;div id=&quot;pdfCaseDetails&quot;&gt;&lt;/div&gt;

    &lt;!-- SECTION 3 --&gt;

    &lt;h2&gt;
        3. Soil Pressure Structural Response Matrix
    &lt;/h2&gt;

    &lt;div id=&quot;pdfPressuresTable&quot;&gt;&lt;/div&gt;

    &lt;!-- SECTION 4 --&gt;

    &lt;h2 style=&quot;page-break-before: always;&quot;&gt;
        4. Soil-Structure Separation Vector Diagram
    &lt;/h2&gt;

    &lt;p&gt;
        The engineering map below outlines the
        precise boundary coordinates of the
        Neutral Axis and associated
        zero-pressure uplift regions.
    &lt;/p&gt;

    &lt;div class=&quot;pdf-diagram&quot;&gt;

        &lt;img
            id=&quot;pdfStaticImageBridge&quot;
            alt=&quot;Footing Structural Analysis Diagram&quot;
        &gt;

    &lt;/div&gt;

    &lt;!-- SECTION 5 --&gt;

    &lt;h2&gt;
        5. Compliance Summary &amp;
        Professional Validation Sign-Off
    &lt;/h2&gt;

    &lt;ul&gt;

        &lt;li&gt;
            The internal calculation engine checks
            soil-structure lift-off for all
            five biaxial loading cases.
        &lt;/li&gt;

        &lt;li&gt;
            Peak edge bearing pressure
            p&lt;sub&gt;max&lt;/sub&gt; must remain within
            allowable SBC limits.
        &lt;/li&gt;

        &lt;li&gt;
            Reinforcement enhancement is required
            if uplift or severe stress
            concentration develops.
        &lt;/li&gt;

    &lt;/ul&gt;

    &lt;!-- SECTION 6 --&gt;

    &lt;h2&gt;
        6. Stability &amp; Geotechnical Validation
    &lt;/h2&gt;

    &lt;div id=&quot;pdfStabilityChecks&quot;&gt;&lt;/div&gt;

    &lt;!-- SIGNATURE BLOCK --&gt;

    &lt;div class=&quot;sign-row&quot;&gt;

        &lt;table
            style=&quot;
                border:none !important;
                margin-top:60px;
                width:100%;
            &quot;
        &gt;

            &lt;tr
                style=&quot;
                    background:transparent !important;
                &quot;
            &gt;

                &lt;td
                    style=&quot;
                        border:none !important;
                        text-align:left;
                        width:50%;
                        padding:0;
                    &quot;
                &gt;

                    &lt;div
                        style=&quot;
                            border-top:1px solid #94a3b8;
                            width:220px;
                            padding-top:5px;
                            color:#475569;
                            font-size:10pt;
                        &quot;
                    &gt;
                        Prepared By:
                        Structural Engineer
                    &lt;/div&gt;

                &lt;/td&gt;

                &lt;td
                    style=&quot;
                        border:none !important;
                        text-align:right;
                        width:50%;
                        padding:0;
                    &quot;
                &gt;

                    &lt;div
                        style=&quot;
                            border-top:1px solid #94a3b8;
                            width:220px;
                            padding-top:5px;
                            color:#475569;
                            font-size:10pt;
                            display:inline-block;
                            text-align:left;
                        &quot;
                    &gt;
                        Approved By:
                        Principal Structural Engineer
                    &lt;/div&gt;

                &lt;/td&gt;

            &lt;/tr&gt;

        &lt;/table&gt;

    &lt;/div&gt;

&lt;/div&gt;
  
  &lt;header&gt;
        &lt;h1&gt;Footing Mechanics Analysis Engine&lt;/h1&gt;
        &lt;p&gt;User Documentation &amp; Mathematical Reference Guide&lt;/p&gt;
    &lt;/header&gt;

    &lt;main&gt;
        &lt;section id=&quot;overview&quot;&gt;
            &lt;h2&gt;1. System Overview&lt;/h2&gt;
            &lt;p&gt;
                The provided JavaScript analysis module evaluates the soil-structure interaction behavior of a rigid rectangular shallow foundation subjected to &lt;strong&gt;axial load ($P$) and biaxial flexure ($M_x, M_y$)&lt;/strong&gt;. It evaluates structural eccentricity ratios, segments the structural response into one of five critical contact mechanics zones, checks geotechnical limits, and renders a live, scaled engineering diagram via an HTML5 canvas.
            &lt;/p&gt;
        &lt;/section&gt;

        &lt;section id=&quot;inputs&quot;&gt;
            &lt;h2&gt;2. Expected Input Fields&lt;/h2&gt;
            &lt;p&gt;The calculation engine binds data from your HTML template via &lt;code&gt;document.getElementById()&lt;/code&gt;. Ensure the following IDs match your input fields exactly:&lt;/p&gt;
            
            &lt;table&gt;
                &lt;thead&gt;
                    &lt;tr&gt;
                        &lt;th&gt;Element ID&lt;/th&gt;
                        &lt;th&gt;Parameter Name&lt;/th&gt;
                        &lt;th&gt;Engineering Description&lt;/th&gt;
                        &lt;th&gt;Expected Unit&lt;/th&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;L&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Footing Length&lt;/td&gt;&lt;td&gt;Dimension parallel to the X-axis (Must be &amp;gt; 0)&lt;/td&gt;&lt;td&gt;meters (m)&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;B&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Footing Width&lt;/td&gt;&lt;td&gt;Dimension parallel to the Y-axis (Must be &amp;gt; 0)&lt;/td&gt;&lt;td&gt;meters (m)&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;P&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Axial Load&lt;/td&gt;&lt;td&gt;Vertical concentric structural load (Must be &amp;gt; 0)&lt;/td&gt;&lt;td&gt;kiloNewtons (kN)&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;Mx&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Moment X&lt;/td&gt;&lt;td&gt;Overturning moment rotating around the X-axis&lt;/td&gt;&lt;td&gt;kN·m&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;My&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Moment Y&lt;/td&gt;&lt;td&gt;Overturning moment rotating around the Y-axis&lt;/td&gt;&lt;td&gt;kN·m&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;qall&lt;/code&gt;&lt;/td&gt;&lt;td&gt;SBC&lt;/td&gt;&lt;td&gt;Allowable Safe Bearing Capacity of the underlying stratum&lt;/td&gt;&lt;td&gt;kN/m²&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;mu&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Friction Coefficient ($\mu$)&lt;/td&gt;&lt;td&gt;Interface sliding friction factor between concrete and soil&lt;/td&gt;&lt;td&gt;dimensionless&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;H&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Horizontal Load&lt;/td&gt;&lt;td&gt;Lateral shear forces driving sliding tendencies&lt;/td&gt;&lt;td&gt;kiloNewtons (kN)&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;t&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Footing Thickness&lt;/td&gt;&lt;td&gt;Total depth/thickness of concrete structural raft slab&lt;/td&gt;&lt;td&gt;meters (m)&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;cx&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Column Width (X)&lt;/td&gt;&lt;td&gt;Structural base column size in the X-direction&lt;/td&gt;&lt;td&gt;meters (m)&lt;/td&gt;&lt;/tr&gt;
                    &lt;tr&gt;&lt;td&gt;&lt;code&gt;cy&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Column Depth (Y)&lt;/td&gt;&lt;td&gt;Structural base column size in the Y-direction&lt;/td&gt;&lt;td&gt;meters (m)&lt;/td&gt;&lt;/tr&gt;
                &lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/section&gt;

        &lt;section id=&quot;mechanics-cases&quot;&gt;
            &lt;h2&gt;3. Structural Contact Mechanics &amp;amp; Case Zonation&lt;/h2&gt;
            &lt;p&gt;Eccentricities are mapped into ratio benchmarks ($r_x = \frac{|M_y|/P}{L}$ and $r_y = \frac{|M_x|/P}{B}$). The algorithm processes the foundation behavior using five distinct kinematic conditions:&lt;/p&gt;

            &lt;div class=&quot;case-card&quot;&gt;
                &lt;h3&gt;Case I: Full Compression ($r_x \le \frac{1}{6}$ AND $r_y \le \frac{1}{6}$)&lt;/h3&gt;
                &lt;p&gt;&lt;strong&gt;Behavior:&lt;/strong&gt; The resultant load stays perfectly within the traditional &quot;Kern&quot; or middle-third bounds. Zero uplift occurs across the envelope.&lt;/p&gt;
                &lt;p&gt;&lt;strong&gt;Governing Equation:&lt;/strong&gt; $$q = \frac{P}{A} \pm \frac{6M_x}{LB^2} \pm \frac{6M_y}{BL^2}$$&lt;/p&gt;
            &lt;/div&gt;

            &lt;div class=&quot;case-card&quot;&gt;
                &lt;h3&gt;Case II: One-Way Lift-Off Along Length ($r_x &amp;gt; \frac{1}{6}$ AND $r_y \le \frac{1}{6}$)&lt;/h3&gt;
                &lt;p&gt;&lt;strong&gt;Behavior:&lt;/strong&gt; Excessive longitudinal eccentricity induces local heel separation. The Neutral Axis runs cleanly parallel to the footing width.&lt;/p&gt;
                &lt;p&gt;&lt;strong&gt;Effective Length ($L_{eff}$):&lt;/strong&gt; $\alpha \cdot L$, where $\alpha = 1.5 - 3r_x$&lt;/p&gt;
            &lt;/div&gt;

            &lt;div class=&quot;case-card&quot;&gt;
                &lt;h3&gt;Case III: One-Way Lift-Off Along Width ($r_y &amp;gt; \frac{1}{6}$ AND $r_x \le \frac{1}{6}$)&lt;/h3&gt;
                &lt;p&gt;&lt;strong&gt;Behavior:&lt;/strong&gt; Excessive lateral eccentricity induces side separation. The Neutral Axis runs parallel to the footing length.&lt;/p&gt;
                &lt;p&gt;&lt;strong&gt;Effective Width ($B_{eff}$):&lt;/strong&gt; $\beta \cdot B$, where $\beta = 1.5 - 3r_y$&lt;/p&gt;
            &lt;/div&gt;

            &lt;div class=&quot;case-card&quot;&gt;
                &lt;h3&gt;Case IV: Pentagonal Compression Zone ($r_x &amp;gt; \frac{1}{6}$, $r_y &amp;gt; \frac{1}{6}$, and $r_x, r_y &amp;lt; 0.5$)&lt;/h3&gt;
                &lt;p&gt;&lt;strong&gt;Behavior:&lt;/strong&gt; Significant biaxial bending causes a single localized corner of the footing to lift off the soil stratum. The effective bearing footprint shifts into a pentagonal layout.&lt;/p&gt;
            &lt;/div&gt;

            &lt;div class=&quot;case-card&quot;&gt;
                &lt;h3&gt;Case V: Triangular Compression Block (Severe Biaxial Overturning)&lt;/h3&gt;
                &lt;p&gt;&lt;strong&gt;Behavior:&lt;/strong&gt; High over-turning moment triggers severe global tilt. Only an isolated triangular wedge remains under active structural compression.&lt;/p&gt;
            &lt;/div&gt;
        &lt;/section&gt;

        &lt;section id=&quot;safety-checks&quot;&gt;
            &lt;h2&gt;4. Automated Geotechnical Safety Frameworks&lt;/h2&gt;
            &lt;p&gt;The code processes and yields key stability triggers inside the target &lt;code&gt;#screenReadout&lt;/code&gt; wrapper element:&lt;/p&gt;
            &lt;ul&gt;
                &lt;li&gt;&lt;strong&gt;Allowable SBC Validation:&lt;/strong&gt; Compares peak pressure ($q_{max}$) against user-provided &lt;code&gt;qall&lt;/code&gt;. Flags an explicit, colored &lt;code&gt;EXCEEDS ALLOWABLE SBC&lt;/code&gt; alert if structural stresses exceed capacities.&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;Factor of Safety (FOS) Calculations:&lt;/strong&gt; Evaluates safety ratios against lateral sliding structural failures ($\frac{\mu \cdot P}{H}$) and mechanical overturning actions ($\frac{\text{Resisting Moment}}{\text{Overturning Moment}}$).&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;Punching Shear Assessment:&lt;/strong&gt; Calculates uniform out-of-plane continuous column punching boundary forces using critical perimeter tracking formulas: $$2 \cdot ((c_x + t) + (c_y + t))$$ Striking thresholds exceeding 1000 kN/m² throws an immediate &lt;code&gt;CRITICAL PUNCHING SHEAR&lt;/code&gt; warning.&lt;/li&gt;
            &lt;/ul&gt;

            &lt;div class=&quot;alert-box&quot;&gt;
                &lt;strong&gt;Critical Structural Warnings Triggered by the Engine:&lt;/strong&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;code&gt;HIGH DIFFERENTIAL SETTLEMENT RISK&lt;/code&gt;: Automatically triggers if your effective compressed structural bearing contact space falls below &lt;strong&gt;70%&lt;/strong&gt;.&lt;/li&gt;
                    &lt;li&gt;&lt;code&gt;HEAVY TOP REINFORCEMENT REQUIRED&lt;/code&gt;: Triggers if tension/uplift is present, or if soil bearing utilization crosses beyond &lt;strong&gt;85%&lt;/strong&gt;.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        &lt;/section&gt;

        &lt;section id=&quot;visualization&quot;&gt;
            &lt;h2&gt;5. Dynamic Blueprint Visualization Canvas&lt;/h2&gt;
            &lt;p&gt;
                The module includes a secondary renderer function named &lt;code&gt;renderEngineeringBlueprint()&lt;/code&gt; which handles real-time scaling and context vector drawing on an HTML canvas element tagged with &lt;code&gt;id=&quot;blueprintCanvas&quot;&lt;/code&gt;.
            &lt;/p&gt;
            &lt;div class=&quot;info-box&quot;&gt;
                &lt;strong&gt;Visual Map Indicators Generated on Canvas:&lt;/strong&gt;
                &lt;ul&gt;
                    &lt;li&gt;&lt;strong style=&quot;color: #0284c7;&quot;&gt;Sky Blue Boundaries:&lt;/strong&gt; The nominal footprint boundaries of your structural base concrete footing.&lt;/li&gt;
                    &lt;li&gt;&lt;strong style=&quot;color: #3b82f6;&quot;&gt;Shaded Inner Polygon:&lt;/strong&gt; The verified region under active structural compression.&lt;/li&gt;
                    &lt;li&gt;&lt;strong style=&quot;color: #dc2626;&quot;&gt;Red Dashed Line:&lt;/strong&gt; The computed Neutral Axis line separating compression zones from soil lift-off regions.&lt;/li&gt;
                    &lt;li&gt;&lt;strong style=&quot;color: #16a34a;&quot;&gt;Green Vector Line:&lt;/strong&gt; Vector highlighting resultant load path displacement showing eccentricity coordinates relative to structural center point.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/div&gt;
        &lt;/section&gt;
    &lt;/main&gt;

&lt;script&gt;
let calculationArchive = null;

function evaluateFootingMechanics() {

    const L = parseFloat(document.getElementById(&#39;L&#39;).value);
    const B = parseFloat(document.getElementById(&#39;B&#39;).value);
    const P = parseFloat(document.getElementById(&#39;P&#39;).value);
    const Mx = parseFloat(document.getElementById(&#39;Mx&#39;).value);
    const My = parseFloat(document.getElementById(&#39;My&#39;).value);

    const qall = parseFloat(document.getElementById(&#39;qall&#39;).value);
    const mu = parseFloat(document.getElementById(&#39;mu&#39;).value);
    const H = parseFloat(document.getElementById(&#39;H&#39;).value);
    const t = parseFloat(document.getElementById(&#39;t&#39;).value);
    const cx = parseFloat(document.getElementById(&#39;cx&#39;).value);
    const cy = parseFloat(document.getElementById(&#39;cy&#39;).value);

    // ==========================================
    // VALIDATION
    // ==========================================
    if (
        isNaN(L) || isNaN(B) || isNaN(P) ||
        L &lt;= 0 || B &lt;= 0 || P &lt;= 0
    ) {
        alert(&quot;L, B and P must be greater than zero.&quot;);
        return;
    }

    // ==========================================
    // ECCENTRICITIES
    // ==========================================
    const ex = Math.abs(My / P);
    const ey = Math.abs(Mx / P);

    const rx = ex / L;
    const ry = ey / B;

    const qavg = P / (L * B);

    // ==========================================
    // INITIALIZE VARIABLES
    // ==========================================
    let caseName = &quot;&quot;;
    let caseDesc = &quot;&quot;;

    let pmax = 0;
    let pmin = 0;

    let alpha = 0;
    let beta = 0;

    let hasUplift = false;

    let naPoints = [];

    let detailedSteps = &quot;&quot;;

    let effectiveArea = L * B;

    let governingEquation = &quot;&quot;;

    let contactPercentage = 100;

    let bearingUtilization = 0;

    let sbcStatus = &quot;SAFE&quot;;

    let fosSliding = 999;

    let fosOverturning = 999;

    let resultantEccentricity = 0;

    let resultantAngle = 0;

    let settlementWarning = &quot;NORMAL&quot;;

    let reinforcementTrigger = &quot;NORMAL&quot;;

    let punchingShear = 0;

    let punchingStatus = &quot;SAFE&quot;;

    let compressionPolygon = [];

    // ==========================================
    // CASE I
    // FULL COMPRESSION
    // ==========================================
    if (
        rx &lt;= 1/6 &amp;&amp;
        ry &lt;= 1/6
    ) {

        caseName = &quot;Case I: Full Compression&quot;;

        caseDesc =
            &quot;Entire footing remains in compression.&quot;;

        governingEquation =
            &quot;q = P/A ± 6Mx/(LB²) ± 6My/(BL²)&quot;;

        pmax =
            qavg * (1 + 6 * rx + 6 * ry);

        pmin =
            qavg * (1 - 6 * rx - 6 * ry);

        hasUplift = false;

        compressionPolygon = [
            [-L/2, -B/2],
            [ L/2, -B/2],
            [ L/2,  B/2],
            [-L/2,  B/2]
        ];

        detailedSteps = `
&lt;h3&gt;Case I: Full Compression&lt;/h3&gt;

&lt;p&gt;
Both eccentricities lie within kern limits.
&lt;/p&gt;

&lt;p&gt;
rₓ = ${rx.toFixed(4)} ≤ 1/6
&lt;/p&gt;

&lt;p&gt;
rᵧ = ${ry.toFixed(4)} ≤ 1/6
&lt;/p&gt;

&lt;p&gt;
Maximum Pressure =
&lt;strong&gt;${pmax.toFixed(3)} kN/m²&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
Minimum Pressure =
&lt;strong&gt;${pmin.toFixed(3)} kN/m²&lt;/strong&gt;
&lt;/p&gt;
`;
    }
  
  

// ====================================================================================
    // CASE II
    // UPLIFT ALONG LENGTH
// ====================================================================================
  
  
  
    else if (
        rx &gt; 1/6 &amp;&amp;
        ry &lt;= 1/6
    ) {

        caseName =
            &quot;Case II: One-Way Lift-Off Along Length&quot;;

        caseDesc =
            &quot;Neutral axis cuts parallel to width.&quot;;

        hasUplift = true;

        alpha =
            Math.max(0.05, 1.5 - 3 * rx);

        const Leff = alpha * L;

        effectiveArea = Leff * B;

        pmax =
            (2 * P) / (3 * effectiveArea);

        pmin = 0;

        const xNA =
            L / 2 - Leff;

        naPoints = [
            { x: xNA, y: -B/2 },
            { x: xNA, y:  B/2 }
        ];

        compressionPolygon = [
            [xNA, -B/2],
            [L/2, -B/2],
            [L/2, B/2],
            [xNA, B/2]
        ];

        detailedSteps = `
&lt;h3&gt;Case II: One-Way Lift-Off Along Length&lt;/h3&gt;

&lt;p&gt;
rₓ = ${rx.toFixed(4)} &gt; 1/6
&lt;/p&gt;

&lt;p&gt;
Effective Compression Length =
${Leff.toFixed(3)} m
&lt;/p&gt;

&lt;p&gt;
Effective Area =
${effectiveArea.toFixed(3)} m²
&lt;/p&gt;

&lt;p&gt;
Maximum Pressure =
&lt;strong&gt;${pmax.toFixed(3)} kN/m²&lt;/strong&gt;
&lt;/p&gt;
`;
    }

    // ==========================================
    // CASE III
    // UPLIFT ALONG WIDTH
    // ==========================================
    else if (
        ry &gt; 1/6 &amp;&amp;
        rx &lt;= 1/6
    ) {

        caseName =
            &quot;Case III: One-Way Lift-Off Along Width&quot;;

        caseDesc =
            &quot;Neutral axis cuts parallel to length.&quot;;

        hasUplift = true;

        beta =
            Math.max(0.05, 1.5 - 3 * ry);

        const Beff = beta * B;

        effectiveArea = L * Beff;

        pmax =
            (2 * P) / (3 * effectiveArea);

        pmin = 0;

        const yNA =
            B / 2 - Beff;

        naPoints = [
            { x: -L/2, y: yNA },
            { x:  L/2, y: yNA }
        ];

        compressionPolygon = [
            [-L/2, yNA],
            [L/2, yNA],
            [L/2, B/2],
            [-L/2, B/2]
        ];

        detailedSteps = `
&lt;h3&gt;Case III: One-Way Lift-Off Along Width&lt;/h3&gt;

&lt;p&gt;
rᵧ = ${ry.toFixed(4)} &gt; 1/6
&lt;/p&gt;

&lt;p&gt;
Effective Compression Width =
${Beff.toFixed(3)} m
&lt;/p&gt;

&lt;p&gt;
Effective Area =
${effectiveArea.toFixed(3)} m²
&lt;/p&gt;

&lt;p&gt;
Maximum Pressure =
&lt;strong&gt;${pmax.toFixed(3)} kN/m²&lt;/strong&gt;
&lt;/p&gt;
`;
    }

    // ==========================================
    // CASE IV
    // PENTAGONAL CONTACT
    // ==========================================
    else if (
        rx &gt; 1/6 &amp;&amp;
        ry &gt; 1/6 &amp;&amp;
        rx &lt; 0.5 &amp;&amp;
        ry &lt; 0.5
    ) {

        caseName =
            &quot;Case IV: Pentagonal Compression Zone&quot;;

        caseDesc =
            &quot;Biaxial uplift with partial corner separation.&quot;;

        hasUplift = true;

        alpha =
            Math.max(0.05, 1.5 - 2 * rx);

        beta =
            Math.max(0.05, 1.5 - 2 * ry);

        effectiveArea =
            L * B *
            (
                1 -
                0.5 *
                (1 - alpha) *
                (1 - beta)
            );

        pmax =
            (2 * P) / effectiveArea;

        pmin = 0;

        naPoints = [
            {
                x: -L/2 + alpha * L,
                y: -B/2
            },
            {
                x: -L/2,
                y: -B/2 + beta * B
            }
        ];

        compressionPolygon = [
            [-L/2 + alpha*L, -B/2],
            [L/2, -B/2],
            [L/2, B/2],
            [-L/2, B/2],
            [-L/2, -B/2 + beta*B]
        ];

        detailedSteps = `
&lt;h3&gt;Case IV: Pentagonal Compression Zone&lt;/h3&gt;

&lt;p&gt;
Both eccentricities exceed kern limits.
&lt;/p&gt;

&lt;p&gt;
Effective Area =
${effectiveArea.toFixed(3)} m²
&lt;/p&gt;

&lt;p&gt;
Maximum Pressure =
&lt;strong&gt;${pmax.toFixed(3)} kN/m²&lt;/strong&gt;
&lt;/p&gt;
`;
    }

    // ==========================================
    // CASE V
    // TRIANGULAR CONTACT
    // ==========================================
    else {

        caseName =
            &quot;Case V: Triangular Compression Block&quot;;

        caseDesc =
            &quot;Extreme overturning with triangular compression region.&quot;;

        hasUplift = true;

        alpha =
            Math.max(0.05, 3 * (0.5 - rx));

        beta =
            Math.max(0.05, 3 * (0.5 - ry));

        effectiveArea =
            0.5 * alpha * beta * L * B;

        pmax =
            (3 * P) / effectiveArea;

        pmin = 0;

        naPoints = [
            {
                x: L/2 - alpha*L,
                y: B/2
            },
            {
                x: L/2,
                y: B/2 - beta*B
            }
        ];

        compressionPolygon = [
            [L/2 - alpha*L, B/2],
            [L/2, B/2],
            [L/2, B/2 - beta*B]
        ];

        detailedSteps = `
&lt;h3&gt;Case V: Triangular Compression Block&lt;/h3&gt;

&lt;p&gt;
Extreme biaxial uplift condition.
&lt;/p&gt;

&lt;p&gt;
Effective Area =
${effectiveArea.toFixed(3)} m²
&lt;/p&gt;

&lt;p&gt;
Maximum Pressure =
&lt;strong&gt;${pmax.toFixed(3)} kN/m²&lt;/strong&gt;
&lt;/p&gt;
`;
    }

    // ==========================================
    // COMMON GEOTECHNICAL CHECKS
    // ==========================================
    const grossArea = L * B;

    contactPercentage =
        (effectiveArea / grossArea) * 100;

    bearingUtilization =
        (pmax / qall) * 100;

    sbcStatus =
        pmax &lt;= qall
            ? &quot;SAFE&quot;
            : &quot;EXCEEDS ALLOWABLE SBC&quot;;

    const resistingForce =
        mu * P;

    fosSliding =
        H &gt; 0
            ? resistingForce / H
            : 999;

    const resistingMoment =
        P * (L / 2);

    const overturningMoment =
        Math.sqrt(Mx * Mx + My * My);

    fosOverturning =
        overturningMoment &gt; 0
            ? resistingMoment / overturningMoment
            : 999;

    resultantEccentricity =
        Math.sqrt(ex * ex + ey * ey);

    resultantAngle =
        Math.atan2(ey, ex) * 180 / Math.PI;

    if (contactPercentage &lt; 70) {

        settlementWarning =
            &quot;HIGH DIFFERENTIAL SETTLEMENT RISK&quot;;
    }

    if (
        hasUplift ||
        pmax &gt; qall * 0.85
    ) {

        reinforcementTrigger =
            &quot;HEAVY TOP REINFORCEMENT REQUIRED&quot;;
    }

    const punchingPerimeter =
        2 * ((cx + t) + (cy + t));

    const punchingArea =
        (cx + t) * (cy + t);

    punchingShear =
        (
            P - qavg * punchingArea
        ) /
        (
            punchingPerimeter * t
        );

    if (punchingShear &gt; 1000) {

        punchingStatus =
            &quot;CRITICAL PUNCHING SHEAR&quot;;
    }

    // ==========================================
    // NEUTRAL AXIS ANGLE
    // ==========================================
    let thetaDeg = 0;

    if (naPoints.length === 2) {

        const dy =
            naPoints[1].y - naPoints[0].y;

        const dx =
            naPoints[1].x - naPoints[0].x;

        thetaDeg =
            Math.abs(
                Math.atan2(dy, dx) *
                180 / Math.PI
            );
    }

    // ==========================================
    // SAVE RESULTS
    // ==========================================
    calculationArchive = {

        L,
        B,
        P,
        Mx,
        My,

        ex,
        ey,

        rx,
        ry,

        qavg,

        pmax,
        pmin,

        alpha,
        beta,

        thetaDeg,

        hasUplift,

        naPoints,

        caseName,
        caseDesc,

        detailedSteps,

        effectiveArea,

        governingEquation,

        contactPercentage,

        bearingUtilization,

        sbcStatus,

        fosSliding,

        fosOverturning,

        resultantEccentricity,

        resultantAngle,

        settlementWarning,

        reinforcementTrigger,

        punchingShear,

        punchingStatus,

        compressionPolygon,

        qall
    };

    // ==========================================
    // SCREEN OUTPUT
    // ==========================================
    document.getElementById(
        &#39;screenReadout&#39;
    ).innerHTML = `

&lt;table&gt;

&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Active Case&lt;/td&gt;
&lt;td&gt;
&lt;span class=&quot;badge ${hasUplift ? &#39;badge-alert&#39; : &#39;&#39;}&quot;&gt;
${caseName}
&lt;/span&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Average Pressure&lt;/td&gt;
&lt;td&gt;${qavg.toFixed(2)} kN/m²&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Maximum Pressure&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;${pmax.toFixed(2)} kN/m²&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Minimum Pressure&lt;/td&gt;
&lt;td&gt;${pmin.toFixed(2)} kN/m²&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Effective Contact Area&lt;/td&gt;
&lt;td&gt;${effectiveArea.toFixed(2)} m²&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Contact Area Percentage&lt;/td&gt;
&lt;td&gt;${contactPercentage.toFixed(1)} %&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Bearing Utilization&lt;/td&gt;
&lt;td&gt;${bearingUtilization.toFixed(1)} %&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Allowable SBC Check&lt;/td&gt;
&lt;td&gt;
&lt;b style=&quot;color:${pmax &lt;= qall ? &#39;#22c55e&#39; : &#39;#ef4444&#39;};&quot;&gt;
${sbcStatus}
&lt;/b&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;FOS Against Sliding&lt;/td&gt;
&lt;td&gt;${fosSliding.toFixed(2)}&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;FOS Against Overturning&lt;/td&gt;
&lt;td&gt;${fosOverturning.toFixed(2)}&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Resultant Eccentricity&lt;/td&gt;
&lt;td&gt;${resultantEccentricity.toFixed(3)} m&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Resultant Vector Angle&lt;/td&gt;
&lt;td&gt;${resultantAngle.toFixed(2)}°&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Settlement Warning&lt;/td&gt;
&lt;td&gt;${settlementWarning}&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Reinforcement Trigger&lt;/td&gt;
&lt;td&gt;${reinforcementTrigger}&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Punching Shear Stress&lt;/td&gt;
&lt;td&gt;${punchingShear.toFixed(2)} kN/m²&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Punching Status&lt;/td&gt;
&lt;td&gt;${punchingStatus}&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;div style=&quot;
margin-top:20px;
padding:15px;
background:#0f172a;
border-radius:8px;
border:1px solid #475569;
line-height:1.7;
&quot;&gt;

&lt;h2 style=&quot;margin-top:0;&quot;&gt;
Detailed Engineering Calculations
&lt;/h2&gt;

${detailedSteps}

&lt;/div&gt;
`;

    renderEngineeringBlueprint(
        L,
        B,
        ex,
        ey,
        hasUplift,
        naPoints,
      	compressionPolygon,
    	pmax
    );
}
  
function renderEngineeringBlueprint(
    L,
    B,
    ex,
    ey,
    hasUplift,
    naPoints,
    compressionPolygon = [],
    pmax = 0
) {

    const canvas = document.getElementById(&#39;blueprintCanvas&#39;);
    const ctx = canvas.getContext(&#39;2d&#39;);

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    const cX = canvas.width / 2;
    const cY = canvas.height / 2;

    const scale = Math.min(
        380 / L,
        300 / B
    );

    const fW = L * scale;
    const fH = B * scale;

    // ==========================================
    // BACKGROUND
    // ==========================================

    ctx.fillStyle = &#39;#ffffff&#39;;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // ==========================================
    // FOOTING OUTLINE
    // ==========================================

    ctx.fillStyle = &#39;#f8fafc&#39;;
    ctx.strokeStyle = &#39;#0284c7&#39;;
    ctx.lineWidth = 3;

    ctx.fillRect(
        cX - fW / 2,
        cY - fH / 2,
        fW,
        fH
    );

    ctx.strokeRect(
        cX - fW / 2,
        cY - fH / 2,
        fW,
        fH
    );

    // ==========================================
    // PRESSURE CONTOUR SHADING
    // ==========================================

    const gradient = ctx.createLinearGradient(
        cX - fW / 2,
        cY - fH / 2,
        cX + fW / 2,
        cY + fH / 2
    );

    gradient.addColorStop(0, &#39;rgba(34,197,94,0.15)&#39;);
    gradient.addColorStop(0.5, &#39;rgba(234,179,8,0.18)&#39;);
    gradient.addColorStop(1, &#39;rgba(239,68,68,0.28)&#39;);

    ctx.fillStyle = gradient;

    ctx.fillRect(
        cX - fW / 2,
        cY - fH / 2,
        fW,
        fH
    );

    // ==========================================
    // GRID LINES
    // ==========================================

    ctx.strokeStyle = &#39;#94a3b8&#39;;
    ctx.lineWidth = 1;
    ctx.setLineDash([4, 4]);

    ctx.beginPath();

    ctx.moveTo(cX - fW / 2 - 25, cY);
    ctx.lineTo(cX + fW / 2 + 25, cY);

    ctx.moveTo(cX, cY - fH / 2 - 25);
    ctx.lineTo(cX, cY + fH / 2 + 25);

    ctx.stroke();

    ctx.setLineDash([]);

    // ==========================================
    // AXIS LABELS
    // ==========================================

    ctx.fillStyle = &#39;#334155&#39;;
    ctx.font = &#39;bold 12px Arial&#39;;

    ctx.fillText(&#39;X&#39;, cX + fW / 2 + 10, cY - 8);
    ctx.fillText(&#39;Y&#39;, cX + 8, cY - fH / 2 - 10);

    // ==========================================
    // COMPRESSION POLYGON
    // ==========================================

    if (compressionPolygon.length &gt;= 2) {

        ctx.fillStyle = &#39;rgba(59,130,246,0.22)&#39;;
        ctx.strokeStyle = &#39;#1d4ed8&#39;;
        ctx.lineWidth = 2;

        ctx.beginPath();

        compressionPolygon.forEach((pt, index) =&gt; {

            const px = cX + pt[0] * scale;
            const py = cY - pt[1] * scale;

            if (index === 0) {
                ctx.moveTo(px, py);
            } else {
                ctx.lineTo(px, py);
            }
        });

        ctx.closePath();
        ctx.fill();
        ctx.stroke();

        // Coordinates labels

        ctx.fillStyle = &#39;#1e3a8a&#39;;
        ctx.font = &#39;11px Arial&#39;;

        compressionPolygon.forEach((pt, i) =&gt; {

            const px = cX + pt[0] * scale;
            const py = cY - pt[1] * scale;

            ctx.beginPath();
            ctx.arc(px, py, 4, 0, Math.PI * 2);
            ctx.fill();

            ctx.fillText(
                `P${i+1}(${pt[0].toFixed(2)}, ${pt[1].toFixed(2)})`,
                px + 8,
                py - 8
            );
        });
    }

    // ==========================================
    // RESULTANT LOCATION
    // ==========================================

    const pX = cX + (ex * scale);
    const pY = cY - (ey * scale);

    // vector line

    ctx.strokeStyle = &#39;#16a34a&#39;;
    ctx.lineWidth = 3;

    ctx.beginPath();
    ctx.moveTo(cX, cY);
    ctx.lineTo(pX, pY);
    ctx.stroke();

    // arrow head

    const angle = Math.atan2(
        pY - cY,
        pX - cX
    );

    const arrowLength = 12;

    ctx.beginPath();

    ctx.moveTo(pX, pY);

    ctx.lineTo(
        pX - arrowLength * Math.cos(angle - Math.PI / 6),
        pY - arrowLength * Math.sin(angle - Math.PI / 6)
    );

    ctx.lineTo(
        pX - arrowLength * Math.cos(angle + Math.PI / 6),
        pY - arrowLength * Math.sin(angle + Math.PI / 6)
    );

    ctx.closePath();

    ctx.fillStyle = &#39;#16a34a&#39;;
    ctx.fill();

    // load point

    ctx.fillStyle = &#39;#ef4444&#39;;

    ctx.beginPath();
    ctx.arc(pX, pY, 8, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = &#39;#ffffff&#39;;
    ctx.font = &#39;bold 10px Arial&#39;;
    ctx.textAlign = &#39;center&#39;;
    ctx.textBaseline = &#39;middle&#39;;

    ctx.fillText(&#39;P&#39;, pX, pY);

    // label

    ctx.fillStyle = &#39;#166534&#39;;
    ctx.font = &#39;bold 12px Arial&#39;;

    ctx.fillText(
        &#39;Resultant Vector&#39;,
        (cX + pX) / 2,
        (cY + pY) / 2 - 10
    );

    // ==========================================
    // UPLIFT REGION
    // ==========================================

    if (hasUplift &amp;&amp; naPoints.length === 2) {

        ctx.fillStyle = &#39;rgba(239,68,68,0.12)&#39;;

        ctx.fillRect(
            cX - fW / 2,
            cY - fH / 2,
            fW,
            fH
        );
    }

    // ==========================================
    // NEUTRAL AXIS
    // ==========================================

    if (hasUplift &amp;&amp; naPoints.length === 2) {

        ctx.strokeStyle = &#39;#dc2626&#39;;
        ctx.lineWidth = 2.5;

        ctx.setLineDash([8, 5]);

        ctx.beginPath();

        ctx.moveTo(
            cX + naPoints[0].x * scale,
            cY - naPoints[0].y * scale
        );

        ctx.lineTo(
            cX + naPoints[1].x * scale,
            cY - naPoints[1].y * scale
        );

        ctx.stroke();

        ctx.setLineDash([]);

        // label

        ctx.fillStyle = &#39;#dc2626&#39;;
        ctx.font = &#39;bold 11px Arial&#39;;
        ctx.textAlign = &#39;left&#39;;

        ctx.fillText(
            &#39;Neutral Axis&#39;,
            cX + naPoints[0].x * scale + 10,
            cY - naPoints[0].y * scale - 10
        );
    }


   // ==========================================
// MAX PRESSURE INDICATOR
// ==========================================

ctx.fillStyle = &#39;#7f1d1d&#39;;
ctx.font = &#39;bold 13px Arial&#39;;
ctx.textAlign = &#39;right&#39;;

var superscriptTwo = String.fromCharCode(178);

ctx.fillText(
    `qmax = ${pmax.toFixed(1)} kN/m` + superscriptTwo,
    canvas.width - 20,
    30
);

    // ==========================================
    // LEGEND
    // ==========================================

    const legendX = 20;
    const legendY = canvas.height - 120;

    ctx.fillStyle = &#39;#0f172a&#39;;
    ctx.fillRect(legendX, legendY, 220, 95);

    ctx.strokeStyle = &#39;#475569&#39;;
    ctx.strokeRect(legendX, legendY, 220, 95);

    ctx.font = &#39;11px Arial&#39;;
    ctx.textAlign = &#39;left&#39;;

    // compression zone

    ctx.fillStyle = &#39;rgba(59,130,246,0.5)&#39;;
    ctx.fillRect(legendX + 10, legendY + 12, 18, 12);

    ctx.fillStyle = &#39;#ffffff&#39;;
    ctx.fillText(
        &#39;Compression Zone&#39;,
        legendX + 38,
        legendY + 22
    );

    // neutral axis

    ctx.strokeStyle = &#39;#dc2626&#39;;
    ctx.setLineDash([6, 4]);

    ctx.beginPath();
    ctx.moveTo(legendX + 10, legendY + 42);
    ctx.lineTo(legendX + 30, legendY + 42);
    ctx.stroke();

    ctx.setLineDash([]);

    ctx.fillStyle = &#39;#ffffff&#39;;

    ctx.fillText(
        &#39;Neutral Axis&#39;,
        legendX + 38,
        legendY + 46
    );

    // resultant vector

    ctx.strokeStyle = &#39;#16a34a&#39;;

    ctx.beginPath();
    ctx.moveTo(legendX + 10, legendY + 68);
    ctx.lineTo(legendX + 30, legendY + 68);
    ctx.stroke();

    ctx.fillText(
        &#39;Resultant Vector&#39;,
        legendX + 38,
        legendY + 72
    );
}

// ==========================================
// ASYNCHRONOUS PDF REPORT GENERATION PIPELINE
// ==========================================

// ==========================================
// ADVANCED PDF EXPORT ENGINE
// High-quality multi-page PDF with:
// ✔ Tables
// ✔ Engineering calculations
// ✔ Canvas drawing
// ✔ Auto page breaks
// ✔ Clean formatting
// ✔ jsPDF + html2canvas
// ==========================================
async function generateProfessionalReportPDF() {

    if (!calculationArchive) {

        alert(
            &quot;Please run footing analysis first.&quot;
        );

        return;
    }

    const s = calculationArchive;

    // ==========================================
    // PREPARE REPORT DATA
    // ==========================================
    document.getElementById(
        &#39;pdfTime&#39;
    ).innerText =
        new Date().toLocaleString();

    // ==========================================
    // INPUT TABLE
    // ==========================================
    document.getElementById(
        &#39;pdfInputsTable&#39;
    ).innerHTML = `

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;
&lt;td&gt;Footing Length (L)&lt;/td&gt;
&lt;td&gt;${s.L.toFixed(3)} m&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Footing Width (B)&lt;/td&gt;
&lt;td&gt;${s.B.toFixed(3)} m&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Axial Load (P)&lt;/td&gt;
&lt;td&gt;${s.P.toFixed(2)} kN&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Moment Mx&lt;/td&gt;
&lt;td&gt;${s.Mx.toFixed(2)} kNm&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Moment My&lt;/td&gt;
&lt;td&gt;${s.My.toFixed(2)} kNm&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Eccentricity ex&lt;/td&gt;
&lt;td&gt;${s.ex.toFixed(4)} m&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Eccentricity ey&lt;/td&gt;
&lt;td&gt;${s.ey.toFixed(4)} m&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Allowable SBC&lt;/td&gt;
&lt;td&gt;${s.qall.toFixed(2)} kN/m²&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;
&lt;/table&gt;
`;

    // ==========================================
    // CASE DETAILS
    // ==========================================
    document.getElementById(
        &#39;pdfCaseDetails&#39;
    ).innerHTML = `

&lt;div style=&quot;
padding:15px;
border:2px solid #1e293b;
border-radius:10px;
background:#f8fafc;
margin-bottom:20px;
&quot;&gt;

&lt;h2 style=&quot;margin-top:0;&quot;&gt;
${s.caseName}
&lt;/h2&gt;

&lt;p&gt;
${s.caseDesc}
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Governing Equation:&lt;/b&gt;
${s.governingEquation}
&lt;/p&gt;

&lt;/div&gt;

&lt;div style=&quot;
padding:15px;
border:1px solid #cbd5e1;
border-radius:8px;
background:white;
line-height:1.8;
&quot;&gt;

${s.detailedSteps}

&lt;/div&gt;
`;

    // ==========================================
    // PRESSURE TABLE
    // ==========================================
    document.getElementById(
        &#39;pdfPressuresTable&#39;
    ).innerHTML = `

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;
&lt;td&gt;Average Pressure&lt;/td&gt;
&lt;td&gt;${s.qavg.toFixed(2)} kN/m²&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Maximum Pressure&lt;/td&gt;
&lt;td&gt;${s.pmax.toFixed(2)} kN/m²&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Minimum Pressure&lt;/td&gt;
&lt;td&gt;${s.pmin.toFixed(2)} kN/m²&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Effective Area&lt;/td&gt;
&lt;td&gt;${s.effectiveArea.toFixed(2)} m²&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Contact Percentage&lt;/td&gt;
&lt;td&gt;${s.contactPercentage.toFixed(1)} %&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Bearing Utilization&lt;/td&gt;
&lt;td&gt;${s.bearingUtilization.toFixed(1)} %&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;
&lt;/table&gt;
`;

    // ==========================================
    // STABILITY TABLE
    // ==========================================
    document.getElementById(
        &#39;pdfStabilityChecks&#39;
    ).innerHTML = `

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;
&lt;td&gt;SBC Check&lt;/td&gt;
&lt;td&gt;${s.pmax.toFixed(2)} / ${s.qall.toFixed(2)}&lt;/td&gt;
&lt;td&gt;${s.sbcStatus}&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;FOS Sliding&lt;/td&gt;
&lt;td&gt;${s.fosSliding.toFixed(2)}&lt;/td&gt;
&lt;td&gt;
${s.fosSliding &gt;= 1.5 ? &#39;SAFE&#39; : &#39;UNSAFE&#39;}
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;FOS Overturning&lt;/td&gt;
&lt;td&gt;${s.fosOverturning.toFixed(2)}&lt;/td&gt;
&lt;td&gt;
${s.fosOverturning &gt;= 2 ? &#39;SAFE&#39; : &#39;UNSAFE&#39;}
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Punching Shear&lt;/td&gt;
&lt;td&gt;${s.punchingShear.toFixed(2)}&lt;/td&gt;
&lt;td&gt;${s.punchingStatus}&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Settlement&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;
${s.settlementWarning}
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Reinforcement&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;
${s.reinforcementTrigger}
&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;
&lt;/table&gt;
`;

    // ==========================================
    // CONVERT CANVAS TO IMAGE
    // ==========================================
    const canvas =
        document.getElementById(
            &#39;blueprintCanvas&#39;
        );

    const imgData =
        canvas.toDataURL(
            &#39;image/png&#39;,
            1.0
        );

    document.getElementById(
        &#39;pdfStaticImageBridge&#39;
    ).src = imgData;

    // ==========================================
    // WAIT FOR DOM RENDER
    // ==========================================
    await new Promise(resolve =&gt;
        setTimeout(resolve, 400)
    );

    // ==========================================
    // GENERATE PDF
    // ==========================================
    const reportElement =
        document.getElementById(
            &#39;pdfReportLayout&#39;
        );

    const reportCanvas =
        await html2canvas(
            reportElement,
            {
                scale: 2,
                useCORS: true,
                backgroundColor: &quot;#ffffff&quot;
            }
        );

    const reportImage =
        reportCanvas.toDataURL(
            &#39;image/jpeg&#39;,
            1.0
        );

    // ==========================================
    // jsPDF SETUP
    // ==========================================
    const {
        jsPDF
    } = window.jspdf;

    const pdf =
        new jsPDF(
            &#39;p&#39;,
            &#39;mm&#39;,
            &#39;a4&#39;
        );

    const pdfWidth =
        pdf.internal.pageSize.getWidth();

    const pdfHeight =
        pdf.internal.pageSize.getHeight();

    const margin = 10;

    const usableWidth =
        pdfWidth - margin * 2;

    const imgWidth =
        usableWidth;

    const imgHeight =
        (
            reportCanvas.height *
            imgWidth
        ) / reportCanvas.width;

    let heightLeft =
        imgHeight;

    let position = 0;

    // ==========================================
    // FIRST PAGE
    // ==========================================
    pdf.addImage(
        reportImage,
        &#39;JPEG&#39;,
        margin,
        position + margin,
        imgWidth,
        imgHeight
    );

    heightLeft -= (
        pdfHeight - margin * 2
    );

    // ==========================================
    // MULTI-PAGE SUPPORT
    // ==========================================
    while (heightLeft &gt; 0) {

        position =
            heightLeft -
            imgHeight +
            margin;

        pdf.addPage();

        pdf.addImage(
            reportImage,
            &#39;JPEG&#39;,
            margin,
            position,
            imgWidth,
            imgHeight
        );

        heightLeft -= (
            pdfHeight - margin * 2
        );
    }

    // ==========================================
    // FOOTER PAGE NUMBERS
    // ==========================================
    const totalPages =
        pdf.internal.getNumberOfPages();

    for (
        let i = 1;
        i &lt;= totalPages;
        i++
    ) {

        pdf.setPage(i);

        pdf.setFontSize(9);

        pdf.text(
            `Page ${i} of ${totalPages}`,
            pdfWidth - 35,
            pdfHeight - 5
        );
    }

    // ==========================================
    // SAVE PDF
    // ==========================================
    pdf.save(
        &#39;Rigorous_Biaxial_Footing_Report.pdf&#39;
    );
}

// ==========================================
// AUTO EXECUTION
// ==========================================

window.onload = () =&gt; {

    evaluateFootingMechanics();

};
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/05/tool-for-analysis-of-isolated-footing.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-8498013643921700976</guid><pubDate>Tue, 26 May 2026 06:25:28 +0000</pubDate><atom:updated>2026-05-26T11:58:44.830+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><category domain="http://www.blogger.com/atom/ns#">Software</category><title>NTKMA PMIS Operating information</title><description>&lt;div style=&quot;font-family: Arial, sans-serif; line-height: 1.8; max-width: 1000px; margin: 0 auto; padding: 25px; background-color: #f9f9f9; border-radius: 10px;&quot;&gt;

    &lt;h1 style=&quot;color: #162f6a; text-align: center;&quot;&gt;How to Use Project Plan Module in NTKMA PMIS&lt;/h1&gt;
    &lt;p style=&quot;text-align: center; font-size: 18px; color: #333;&quot;&gt;&lt;strong&gt;Step-by-Step Detailed Explanation for Adding Tasks, Subtasks, Activities &amp;amp; All Important Features&lt;/strong&gt;&lt;/p&gt;

    &lt;hr style=&quot;border: 2px solid #ff9f00;&quot;&gt;

    &lt;h2 style=&quot;color: #162f6a;&quot;&gt;1. Overview of Project Plan Module&lt;/h2&gt;
    &lt;p&gt;This module is used to create a detailed &lt;strong&gt;Work Breakdown Structure (WBS)&lt;/strong&gt; for infrastructure projects under Nashik Trimbakeshwar Kumbh Mela 2027. It allows you to define:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;Tasks&lt;/strong&gt; – Major work items&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Subtasks&lt;/strong&gt; – Detailed breakdown under tasks&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Activities&lt;/strong&gt; – Granular level items for progress tracking&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Once the plan is &lt;strong&gt;Verified&lt;/strong&gt;, editing becomes restricted.&lt;/p&gt;

    &lt;h2 style=&quot;color: #162f6a;&quot;&gt;2. Initial Steps After Opening the Page&lt;/h2&gt;
    &lt;ol&gt;
        &lt;li&gt;Select your &lt;strong&gt;Project&lt;/strong&gt; from the top dropdown menu.&lt;/li&gt;
        &lt;li&gt;The system automatically checks the verification status (&lt;code&gt;data-isverifiedplan&lt;/code&gt;).&lt;/li&gt;
        &lt;li&gt;If the plan is already verified:
            &lt;ul&gt;
                &lt;li&gt;“Add Task” button will be hidden.&lt;/li&gt;
                &lt;li&gt;Most editing options will be disabled.&lt;/li&gt;
                &lt;li&gt;You will see warning messages when trying to edit.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ol&gt;

    &lt;h2 style=&quot;color: #162f6a;&quot;&gt;3. Adding Tasks &amp;amp; Subtasks&lt;/h2&gt;

    &lt;h3 style=&quot;color: #ff9f00;&quot;&gt;Method A: Using Main “Add Task” Button (Recommended for new projects)&lt;/h3&gt;
    &lt;ol&gt;
        &lt;li&gt;Click the green button &lt;strong&gt;“Add Task”&lt;/strong&gt;.&lt;/li&gt;
        &lt;li&gt;A modal window opens with a treeview structure.&lt;/li&gt;
        &lt;li&gt;Enter &lt;strong&gt;Task Name&lt;/strong&gt;, &lt;strong&gt;Start Date&lt;/strong&gt;, and &lt;strong&gt;End Date&lt;/strong&gt;.&lt;/li&gt;
        &lt;li&gt;Click the &lt;strong&gt;+&lt;/strong&gt; (plus) button next to the task.&lt;/li&gt;
        &lt;li&gt;You will get two options:
            &lt;ul&gt;
                &lt;li&gt;&lt;strong&gt;Add Same Level&lt;/strong&gt; → Add another task at the same hierarchy level.&lt;/li&gt;
                &lt;li&gt;&lt;strong&gt;Add Sub Level&lt;/strong&gt; → Create a &lt;strong&gt;Subtask&lt;/strong&gt; under the current task.&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;Continue adding tasks and subtasks as needed.&lt;/li&gt;
        &lt;li&gt;Click &lt;strong&gt;“Create Task”&lt;/strong&gt; at the bottom to save all tasks in bulk.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3 style=&quot;color: #ff9f00;&quot;&gt;Method B: Add Task/Subtask Under Existing Task&lt;/h3&gt;
    &lt;ol&gt;
        &lt;li&gt;In the main task table, click the &lt;strong&gt;+&lt;/strong&gt; icon next to any existing task.&lt;/li&gt;
        &lt;li&gt;A popup modal will open.&lt;/li&gt;
        &lt;li&gt;Add new task or subtask and save.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Click on any parent task row in the table to expand or collapse its subtasks.&lt;/p&gt;

    &lt;h2 style=&quot;color: #162f6a;&quot;&gt;4. Adding &amp;amp; Managing Activities&lt;/h2&gt;
    &lt;ol&gt;
        &lt;li&gt;Click the red button &lt;strong&gt;“Add/Delete Activity”&lt;/strong&gt;.&lt;/li&gt;
        &lt;li&gt;The screen splits: Left side shows Tasks &amp;amp; Subtasks tree, Right side shows activities.&lt;/li&gt;
        &lt;li&gt;Click on any Task/Subtask on the left panel.&lt;/li&gt;
        &lt;li&gt;On the right side, fill details for each activity:
            &lt;ul&gt;
                &lt;li&gt;Activity Title&lt;/li&gt;
                &lt;li&gt;Unit of Measurement (Km, Nos, Cum, etc.)&lt;/li&gt;
                &lt;li&gt;Target Value&lt;/li&gt;
                &lt;li&gt;Start Date &amp;amp; End Date&lt;/li&gt;
            &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;Click &lt;strong&gt;“Save Activity”&lt;/strong&gt;.&lt;/li&gt;
        &lt;li&gt;You can add multiple activities for one task.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h2 style=&quot;color: #162f6a;&quot;&gt;5. Other Important Tools &amp;amp; Features&lt;/h2&gt;

    &lt;h3 style=&quot;color: #ff9f00;&quot;&gt;A. Task/Sub-Task Weightage&lt;/h3&gt;
    &lt;p&gt;Click the yellow button &lt;strong&gt;“Task/Sub-Task Weightage”&lt;/strong&gt;. This opens a separate page where you assign percentage weight to each task and subtask. Total must be &lt;strong&gt;100%&lt;/strong&gt;. This is crucial for overall progress calculation.&lt;/p&gt;

    &lt;h3 style=&quot;color: #ff9f00;&quot;&gt;B. Reset Task / Subtask Sequence&lt;/h3&gt;
    &lt;ol&gt;
        &lt;li&gt;Click &lt;strong&gt;“Reset Task Sequence”&lt;/strong&gt; or &lt;strong&gt;“Reset Sub Task Sequence”&lt;/strong&gt; button.&lt;/li&gt;
        &lt;li&gt;Drag and drop rows to reorder.&lt;/li&gt;
        &lt;li&gt;Click &lt;strong&gt;“Update Task Sequence”&lt;/strong&gt; to save the new order.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3 style=&quot;color: #ff9f00;&quot;&gt;C. Task Dependencies&lt;/h3&gt;
    &lt;ol&gt;
        &lt;li&gt;Click the chain-link icon on any task.&lt;/li&gt;
        &lt;li&gt;In the modal, you can link the current task to other tasks (same project or different projects).&lt;/li&gt;
        &lt;li&gt;This creates logical dependencies (e.g., Task B cannot start before Task A is finished).&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3 style=&quot;color: #ff9f00;&quot;&gt;D. View Project Plan&lt;/h3&gt;
    &lt;p&gt;Click the blue button &lt;strong&gt;“View Project Plan”&lt;/strong&gt; to download a complete visual project schedule (usually in PDF format with Gantt chart view).&lt;/p&gt;

    &lt;h3 style=&quot;color: #ff9f00;&quot;&gt;E. Update Physical Progress&lt;/h3&gt;
    &lt;p&gt;Click the blue button &lt;strong&gt;“Update Physical Progress”&lt;/strong&gt;. This takes you to another module where you can update actual % completion of activities.&lt;/p&gt;

    &lt;h3 style=&quot;color: #ff9f00;&quot;&gt;F. Activity Sequence Reset&lt;/h3&gt;
    &lt;ol&gt;
        &lt;li&gt;Inside Activity view, click &lt;strong&gt;“Reset Sequence”&lt;/strong&gt;.&lt;/li&gt;
        &lt;li&gt;Drag and drop activities to change order.&lt;/li&gt;
        &lt;li&gt;Click &lt;strong&gt;“Update Activity Sequence”&lt;/strong&gt; to save.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h2 style=&quot;color: #162f6a;&quot;&gt;6. Action Buttons Summary&lt;/h2&gt;

    &lt;table border=&quot;1&quot; cellpadding=&quot;12&quot; cellspacing=&quot;0&quot; style=&quot;width:100%; border-collapse: collapse; margin: 20px 0; background:white;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background-color: #162f6a; color: white;&quot;&gt;
                &lt;th&gt;Button&lt;/th&gt;
                &lt;th&gt;Function&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Add Task&lt;/strong&gt; (Green)&lt;/td&gt;&lt;td&gt;Add new tasks &amp;amp; subtasks&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Add/Delete Activity&lt;/strong&gt; (Red)&lt;/td&gt;&lt;td&gt;Manage detailed activities&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Task/Sub-Task Weightage&lt;/strong&gt; (Yellow)&lt;/td&gt;&lt;td&gt;Assign weight percentages&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;&lt;strong&gt;View Project Plan&lt;/strong&gt; (Blue)&lt;/td&gt;&lt;td&gt;Download complete plan&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Update Physical Progress&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Update % completion&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Back to Task List&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Return to main task view&lt;/td&gt;&lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;h2 style=&quot;color: #162f6a;&quot;&gt;7. Critical Restrictions – Verified Plan&lt;/h2&gt;
    &lt;div style=&quot;background-color: #f8d7da; padding: 20px; border-radius: 8px; border-left: 6px solid #dc3545; margin: 20px 0;&quot;&gt;
        &lt;strong&gt;⚠ Important Warning:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
        Once the Project Plan is &lt;strong&gt;Verified&lt;/strong&gt; by higher authorities:
        &lt;ul&gt;
            &lt;li&gt;You cannot add, edit, or delete Tasks, Subtasks, or Activities.&lt;/li&gt;
            &lt;li&gt;Only Physical Progress updating is allowed.&lt;/li&gt;
            &lt;li&gt;Contact PMU (Project Monitoring Unit) or MIS Expert for any changes.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;h2 style=&quot;color: #162f6a;&quot;&gt;8. Recommended Best Workflow&lt;/h2&gt;
    &lt;ol&gt;
        &lt;li&gt;Select Project&lt;/li&gt;
        &lt;li&gt;Add all Tasks &amp;amp; Subtasks using “Add Task”&lt;/li&gt;
        &lt;li&gt;Add detailed Activities under each task&lt;/li&gt;
        &lt;li&gt;Set Task/Subtask Weightage (Total 100%)&lt;/li&gt;
        &lt;li&gt;Define Dependencies where required&lt;/li&gt;
        &lt;li&gt;Reset sequence if needed&lt;/li&gt;
        &lt;li&gt;Review using “View Project Plan”&lt;/li&gt;
        &lt;li&gt;Finally, get the plan verified&lt;/li&gt;
    &lt;/ol&gt;

    &lt;hr&gt;
    &lt;p style=&quot;text-align: center; color: #555; font-size: 15px;&quot;&gt;
        &lt;strong&gt;Need Help?&lt;/strong&gt; Contact PMIS Expert, for Nashik Trimbakeshwar Kumbh Mela Project Monitoring Information System (PMIS)
    &lt;/p&gt;

&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/05/ntkma-pmis-operating-information.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-4261175496075075260</guid><pubDate>Tue, 05 May 2026 12:08:19 +0000</pubDate><atom:updated>2026-05-21T18:11:21.619+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Estimate Preparation</category><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><title>Estimate Calculation Tool (SSR 2022-23)</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;PWD SSR Estimate Tool&lt;/title&gt;
    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.0/papaparse.min.js&quot;&gt;&lt;/script&gt;
    &lt;style&gt;
        :root { --primary: #2c3e50; --accent: #3498db; --success: #27ae60; }
        body { font-family: &#39;Segoe UI&#39;, sans-serif; margin: 2px; background: #f8f9fa; color: #333; }
        .container { max-width: 1300px; margin: auto; background: white; padding: 2px; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
        .grid-header { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 20px; padding: 2px; background: #eef2f3; border-radius: 6px; }
        .status-bar { padding: 2px; margin-bottom: 15px; border-radius: 4px; font-weight: bold; text-align: center; }
        .loading { background: #fff3cd; color: #856404; }
        .ready { background: #d4edda; color: #155724; }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; font-size: 13px; }
        th, td { border: 1px solid #dee2e6; padding: 2px; text-align: left; }
        th { background: var(--primary); color: white; position: sticky; top: 0; }
        tr:nth-child(even) { background: #f2f2f2; }
        .summary-panel { margin-top: 30px; display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
        .box { padding: 2px; border: 1px solid #ddd; border-radius: 5px; background: #fff; margin-bottom: 20px; }
        input, select { width: 100%; padding: 2px; box-sizing: border-box; border: 1px solid #ccc; border-radius: 4px; }
        .btn { background: var(--success); color: white; border: none; padding: 2px 2px; cursor: pointer; border-radius: 4px; font-weight: bold; }
        .btn:disabled { background: #ccc; }
        .table-container { max-height: 400px; overflow-y: auto; border: 1px solid #ddd; margin-top: 20px; }
        th { position: sticky; top: 0; z-index: 10; }
        .project-bar { display: flex; gap: 10px; background: #34495e; padding: 2px; border-radius: 6px; margin-bottom: 20px; color: white; align-items: center; }
        .project-bar input, .project-bar select { width: auto; flex-grow: 1; }
        .btn-edit { background: #f39c12; padding: 2px 2px; font-size: 11px; margin-right: 5px; }
        .btn-delete { background: #e74c3c; padding: 2px 2px; font-size: 11px; }
        .btn-export { background: #9b59b6; }
        .btn-save { background: #2980b9; }
      .highlight{
    background:#fff3cd;
    padding:12px;
    border-left:5px solid #ff9800;
    margin:15px 0;
}
.formula{
    background:#e8f5e9;
    padding:12px;
    border-left:5px solid #2e7d32;
    font-weight:bold;
    margin:15px 0;
}
      code{
    background:#eef2f5;
    padding:2px 6px;
    border-radius:4px;
    color:#c62828;
}
pre{
    background:#272822;
    color:#f8f8f2;
    padding:15px;
    overflow:auto;
    border-radius:6px;
}
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  
  &lt;amp-auto-ads type=&quot;adsense&quot;
        data-ad-client=&quot;ca-pub-2103856900504884&quot;&gt;
&lt;/amp-auto-ads&gt;

&lt;div class=&quot;container&quot;&gt;
    &lt;h2&gt;Estimate Calculation Tool (SSR 2022-23)&lt;/h2&gt;
    &lt;div id=&quot;status&quot; class=&quot;status-bar loading&quot;&gt;Initializing connection to Google Sheets...&lt;/div&gt;
  
    &lt;div class=&quot;project-bar&quot;&gt;
        &lt;input type=&quot;text&quot; id=&quot;projectName&quot; placeholder=&quot;Project Name (e.g. Bridge at Km 5/200)&quot;&gt;
        &lt;select id=&quot;projectList&quot; onchange=&quot;loadProject(this.value)&quot;&gt;
            &lt;option value=&quot;&quot;&gt;-- Load Saved Project --&lt;/option&gt;
        &lt;/select&gt;
    &lt;/div&gt;
    
    &lt;div class=&quot;project-bar&quot;&gt;
        &lt;button class=&quot;btn btn-save&quot; onclick=&quot;saveToDB()&quot;&gt;Save Project&lt;/button&gt;
        &lt;button class=&quot;btn btn-export&quot; onclick=&quot;exportJSON()&quot;&gt;Export JSON&lt;/button&gt;
        &lt;input type=&quot;file&quot; id=&quot;importFile&quot; style=&quot;display:none&quot; onchange=&quot;importJSON(event)&quot;&gt;
        &lt;button class=&quot;btn&quot; onclick=&quot;document.getElementById(&#39;importFile&#39;).click()&quot;&gt;Import JSON&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;grid-header&quot;&gt;
        &lt;div&gt;
            &lt;label&gt;Lead Distance (km)&lt;/label&gt;
            &lt;input type=&quot;number&quot; id=&quot;leadDist&quot; placeholder=&quot;Enter Lead km&quot; oninput=&quot;recalculateAll()&quot;&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label&gt;Cess (%)&lt;/label&gt;
            &lt;input type=&quot;number&quot; id=&quot;cessInput&quot; value=&quot;1&quot; oninput=&quot;recalculateAll()&quot;&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label&gt;Area/Tribal Charges (%)&lt;/label&gt;
            &lt;select id=&quot;areaCharge&quot; onchange=&quot;recalculateAll()&quot;&gt;
                &lt;option value=&quot;0&quot;&gt;None (0%)&lt;/option&gt;
                &lt;option value=&quot;10&quot;&gt;Tribal (10%)&lt;/option&gt;
                &lt;option value=&quot;5&quot;&gt;Jail Premises (5%)&lt;/option&gt;
                &lt;option value=&quot;15&quot;&gt;Municipal (15%)&lt;/option&gt;
            &lt;/select&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;grid-header&quot; style=&quot;background: #d1ecf1;&quot;&gt;
        &lt;div style=&quot;flex: 2;&quot;&gt;
            &lt;label&gt;SSR Item No.&lt;/label&gt;
            &lt;input type=&quot;text&quot; id=&quot;itemSearch&quot; placeholder=&quot;e.g. Bd-A.1&quot;&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label&gt;Quantity&lt;/label&gt;
            &lt;input type=&quot;number&quot; id=&quot;itemQty&quot; value=&quot;1&quot;&gt;
        &lt;/div&gt;
        &lt;div style=&quot;display: flex; align-items: flex-end;&quot;&gt;
            &lt;button id=&quot;addBtn&quot; class=&quot;btn&quot; onclick=&quot;addItem()&quot; disabled&gt;Add Item&lt;/button&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;table-container&quot;&gt;
        &lt;table id=&quot;mainTable&quot;&gt;
            &lt;thead&gt;
                &lt;tr&gt;
                    &lt;th&gt;Item No&lt;/th&gt;
                    &lt;th&gt;Description&lt;/th&gt;
                    &lt;th&gt;Unit&lt;/th&gt;
                    &lt;th&gt;Qty&lt;/th&gt;
                    &lt;th&gt;SSR Rate&lt;/th&gt;
                    &lt;th&gt;Net Rate&lt;/th&gt;
                    &lt;th&gt;Lead&lt;/th&gt;
                    &lt;th&gt;Final Rate&lt;/th&gt;
                    &lt;th&gt;Amount&lt;/th&gt;
                    &lt;th&gt;Actions&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody id=&quot;tableBody&quot;&gt;&lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;
  
    &lt;div class=&quot;summary-panel&quot;&gt;  
        &lt;div class=&quot;box&quot;&gt;
            &lt;h3&gt;Project Abstract&lt;/h3&gt;
            &lt;div id=&quot;abstractSummary&quot;&gt;Total Cost calculations will appear here.&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  &lt;div class=&quot;summary-panel&quot;&gt;  
        &lt;div class=&quot;box&quot;&gt;
            &lt;h3&gt;Material Consumption Summary&lt;/h3&gt;
            &lt;div id=&quot;materialSummary&quot;&gt;Enter items to see consumption...&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
  
  &lt;div class=&quot;container&quot;&gt;

&lt;h1&gt;Functioning of this tool&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;SSR-based estimation&lt;/li&gt;
&lt;li&gt;Material consumption analysis&lt;/li&gt;
&lt;li&gt;Lead charge calculations&lt;/li&gt;
&lt;li&gt;BOQ preparation&lt;/li&gt;
&lt;li&gt;GST and abstract generation&lt;/li&gt;
&lt;li&gt;Project storage and retrieval&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;1. Purpose of the System&lt;/h2&gt;

&lt;p&gt;
The software behaves like a digital estimation office used in:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PWD Departments&lt;/li&gt;
&lt;li&gt;MoRTH Projects&lt;/li&gt;
&lt;li&gt;Irrigation Works&lt;/li&gt;
&lt;li&gt;Building Construction&lt;/li&gt;
&lt;li&gt;Road Projects&lt;/li&gt;
&lt;li&gt;Bridge Works&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Engineering Activity&lt;/th&gt;
&lt;th&gt;Code Function&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;SSR Item Selection&lt;/td&gt;
&lt;td&gt;&lt;code&gt;addItem()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Lead Charge Calculation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;interpolateLead()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Rate Analysis&lt;/td&gt;
&lt;td&gt;&lt;code&gt;recalculateAll()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Estimate Abstract&lt;/td&gt;
&lt;td&gt;&lt;code&gt;updateSummaries()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Project Saving&lt;/td&gt;
&lt;td&gt;&lt;code&gt;saveToDB()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;hr&gt;

&lt;h2&gt;2. Database Initialization&lt;/h2&gt;

&lt;pre&gt;
const request = indexedDB.open(&quot;PWDEstimateDB&quot;, 1);
&lt;/pre&gt;

&lt;p&gt;
This creates a local browser database for storing projects.
&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;
Equivalent Civil Engineering Meaning:
&lt;ul&gt;
&lt;li&gt;Digital Estimate Register&lt;/li&gt;
&lt;li&gt;DPR File Storage&lt;/li&gt;
&lt;li&gt;Tender Estimate Archive&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;p&gt;
Each project is saved using:
&lt;/p&gt;

&lt;pre&gt;
db.createObjectStore(&quot;projects&quot;, { keyPath: &quot;name&quot; });
&lt;/pre&gt;

&lt;p&gt;
Example Project Names:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Construction of CC Road&lt;/li&gt;
&lt;li&gt;Bridge Repair Estimate&lt;/li&gt;
&lt;li&gt;Road Widening Work&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;3. SSR and Lead Data Loading&lt;/h2&gt;

&lt;pre&gt;
const SSR_CSV = &quot;...&quot;;
const LEAD_CSV = &quot;...&quot;;
&lt;/pre&gt;

&lt;p&gt;
The software loads:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSR Schedule of Rates&lt;/li&gt;
&lt;li&gt;Lead Charge Tables&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;SSR Sheet Contains&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Item Codes&lt;/li&gt;
&lt;li&gt;Descriptions&lt;/li&gt;
&lt;li&gt;Units&lt;/li&gt;
&lt;li&gt;SSR Rates&lt;/li&gt;
&lt;li&gt;Material Consumption Factors&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Lead Sheet Contains&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Murum Lead Rates&lt;/li&gt;
&lt;li&gt;Sand Transportation Rates&lt;/li&gt;
&lt;li&gt;Metal Lead Charges&lt;/li&gt;
&lt;li&gt;Cement Transportation Costs&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;4. Material Mapping Logic&lt;/h2&gt;

&lt;pre&gt;
const materialMapping = {
    &quot;Murum&quot;: &#39;D&#39;,
    &quot;Natural Sand&quot;: &#39;J&#39;
}
&lt;/pre&gt;

&lt;p&gt;
This maps materials to their corresponding lead-rate columns.
&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;
Engineering Meaning:
&lt;p&gt;
If Murum transportation rates are stored in Column D,
the software automatically fetches transportation charges from Column D.
&lt;/p&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;5. Material Consumption Factors&lt;/h2&gt;

&lt;pre&gt;
const matColumns = {
    &quot;Cement&quot;: &#39;K&#39;,
    &quot;Steel&quot;: &#39;P&#39;
}
&lt;/pre&gt;

&lt;p&gt;
Every SSR item consumes materials.
The software extracts these automatically.
&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;SSR Item&lt;/th&gt;
&lt;th&gt;Cement&lt;/th&gt;
&lt;th&gt;Sand&lt;/th&gt;
&lt;th&gt;Aggregate&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;PCC 1:4:8&lt;/td&gt;
&lt;td&gt;1.5 Bags&lt;/td&gt;
&lt;td&gt;0.45 m³&lt;/td&gt;
&lt;td&gt;0.90 m³&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;div class=&quot;highlight&quot;&gt;
This enables:
&lt;ul&gt;
&lt;li&gt;Material Statements&lt;/li&gt;
&lt;li&gt;Quarry Planning&lt;/li&gt;
&lt;li&gt;Lead Analysis&lt;/li&gt;
&lt;li&gt;Royalty Estimation&lt;/li&gt;
&lt;li&gt;Transport Logistics&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;6. Initialization Function&lt;/h2&gt;

&lt;pre&gt;
async function init()
&lt;/pre&gt;

&lt;p&gt;
This initializes the entire estimating system.
&lt;/p&gt;

&lt;p&gt;
It:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloads SSR Data&lt;/li&gt;
&lt;li&gt;Downloads Lead Data&lt;/li&gt;
&lt;li&gt;Parses Spreadsheets&lt;/li&gt;
&lt;li&gt;Activates Estimation Engine&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;7. Column Letter Conversion&lt;/h2&gt;

&lt;pre&gt;
function letterToIdx(letter)
&lt;/pre&gt;

&lt;p&gt;
Converts spreadsheet columns:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A → 0&lt;/li&gt;
&lt;li&gt;B → 1&lt;/li&gt;
&lt;li&gt;AA → 26&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This bridges spreadsheet engineering data with software calculations.
&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;8. Lead Charge Interpolation&lt;/h2&gt;

&lt;pre&gt;
function interpolateLead(dist, colLetter)
&lt;/pre&gt;

&lt;p&gt;
This is the most important engineering calculation in the software.
&lt;/p&gt;

&lt;h3&gt;Engineering Principle&lt;/h3&gt;

&lt;p&gt;
Lead rates are available at fixed intervals.
&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Distance&lt;/th&gt;
&lt;th&gt;Lead Rate&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;5 km&lt;/td&gt;
&lt;td&gt;₹120&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;10 km&lt;/td&gt;
&lt;td&gt;₹180&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;
If actual lead distance is 7 km,
the software calculates intermediate transportation rate automatically.
&lt;/p&gt;

&lt;div class=&quot;formula&quot;&gt;
Interpolation Formula:&lt;br&gt;&lt;br&gt;

y = y1 + ((x - x1) × (y2 - y1) / (x2 - x1))
&lt;/div&gt;

&lt;div class=&quot;highlight&quot;&gt;
Used In:
&lt;ul&gt;
&lt;li&gt;Earthwork&lt;/li&gt;
&lt;li&gt;Road Construction&lt;/li&gt;
&lt;li&gt;Canal Excavation&lt;/li&gt;
&lt;li&gt;Bridge Works&lt;/li&gt;
&lt;li&gt;Embankment Projects&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;9. Adding SSR Items&lt;/h2&gt;

&lt;pre&gt;
function addItem()
&lt;/pre&gt;

&lt;p&gt;
This acts like BOQ entry software.
&lt;/p&gt;

&lt;p&gt;
Engineer enters:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSR Item Code&lt;/li&gt;
&lt;li&gt;Quantity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The system:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Searches SSR Database&lt;/li&gt;
&lt;li&gt;Retrieves Rates&lt;/li&gt;
&lt;li&gt;Adds Item to Estimate&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;10. Quantity Editing &amp; Deletion&lt;/h2&gt;

&lt;pre&gt;
editItem()
deleteItem()
&lt;/pre&gt;

&lt;p&gt;
Equivalent to:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BOQ Revision&lt;/li&gt;
&lt;li&gt;Quantity Corrections&lt;/li&gt;
&lt;li&gt;Variation Statement Modifications&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;11. Project Saving&lt;/h2&gt;

&lt;pre&gt;
saveToDB()
&lt;/pre&gt;

&lt;p&gt;
Stores:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estimate Items&lt;/li&gt;
&lt;li&gt;Lead Distances&lt;/li&gt;
&lt;li&gt;Cess Settings&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;
Equivalent Civil Engineering Meaning:
&lt;ul&gt;
&lt;li&gt;Saving DPR Files&lt;/li&gt;
&lt;li&gt;Tender Estimate Storage&lt;/li&gt;
&lt;li&gt;Project Archive&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;12. Recalculation Engine&lt;/h2&gt;

&lt;pre&gt;
function recalculateAll()
&lt;/pre&gt;

&lt;p&gt;
This is the core estimation engine.
&lt;/p&gt;

&lt;h3&gt;Step 1 – Material Consumption&lt;/h3&gt;

&lt;pre&gt;
matTotals[m] += factor * item.inputQty;
&lt;/pre&gt;

&lt;p&gt;
Example:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PCC requires 2 cement bags/m³&lt;/li&gt;
&lt;li&gt;Quantity = 10 m³&lt;/li&gt;
&lt;li&gt;Total Cement = 20 Bags&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;13. Net SSR Rate Calculation&lt;/h2&gt;

&lt;pre&gt;
const netRate = ssrRate - (ssrRate * cessFact);
&lt;/pre&gt;

&lt;p&gt;
This deducts:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Labour Cess&lt;/li&gt;
&lt;li&gt;Department Recoveries&lt;/li&gt;
&lt;li&gt;Royalty Adjustments&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;14. Lead Charge Calculation&lt;/h2&gt;

&lt;pre&gt;
itemLeadCost += (factor * leadRate);
&lt;/pre&gt;

&lt;p&gt;
Calculates transportation cost of each material.
&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Material&lt;/th&gt;
&lt;th&gt;Consumption&lt;/th&gt;
&lt;th&gt;Lead Rate&lt;/th&gt;
&lt;th&gt;Lead Cost&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Cement&lt;/td&gt;
&lt;td&gt;5 Bags&lt;/td&gt;
&lt;td&gt;₹12/Bag&lt;/td&gt;
&lt;td&gt;₹60&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;hr&gt;

&lt;h2&gt;15. Final Rate Derivation&lt;/h2&gt;

&lt;pre&gt;
finalRate = netRate + itemLeadCost
&lt;/pre&gt;

&lt;p&gt;
Final item rate includes:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Net SSR Rate&lt;/li&gt;
&lt;li&gt;Transportation Escalation&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;16. Amount Calculation&lt;/h2&gt;

&lt;pre&gt;
amount = finalRate × quantity
&lt;/pre&gt;

&lt;div class=&quot;formula&quot;&gt;
Amount = Rate × Quantity
&lt;/div&gt;

&lt;p&gt;
Equivalent to standard BOQ calculations.
&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;17. Material Summary&lt;/h2&gt;

&lt;pre&gt;
updateSummaries()
&lt;/pre&gt;

&lt;p&gt;
Generates:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Material Statements&lt;/li&gt;
&lt;li&gt;Lead Statements&lt;/li&gt;
&lt;li&gt;Consumption Abstracts&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Material&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;Lead&lt;/th&gt;
&lt;th&gt;Charges&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Cement&lt;/td&gt;
&lt;td&gt;250 Bags&lt;/td&gt;
&lt;td&gt;40 km&lt;/td&gt;
&lt;td&gt;₹15,000&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Sand&lt;/td&gt;
&lt;td&gt;18 m³&lt;/td&gt;
&lt;td&gt;12 km&lt;/td&gt;
&lt;td&gt;₹7,200&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;hr&gt;

&lt;h2&gt;18. GST Calculation&lt;/h2&gt;

&lt;pre&gt;
const gst = grandTotal * 0.18;
&lt;/pre&gt;

&lt;p&gt;
Adds 18% GST to estimate.
&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;19. Estimate Abstract&lt;/h2&gt;

&lt;p&gt;
Final Estimate:
&lt;/p&gt;

&lt;div class=&quot;formula&quot;&gt;
Grand Total = Civil Cost + Lead Charges + GST
&lt;/div&gt;

&lt;p&gt;
Equivalent to:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Administrative Approval Abstract&lt;/li&gt;
&lt;li&gt;Tender Schedule Amount&lt;/li&gt;
&lt;li&gt;DPR Cost Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;20. Dynamic Material Leads&lt;/h2&gt;

&lt;pre&gt;
updateLeadDist(material, val)
&lt;/pre&gt;

&lt;p&gt;
Allows separate lead distances for each material.
&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Material&lt;/th&gt;
&lt;th&gt;Lead Distance&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Murum&lt;/td&gt;
&lt;td&gt;8 km&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Sand&lt;/td&gt;
&lt;td&gt;35 km&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Cement&lt;/td&gt;
&lt;td&gt;120 km&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;div class=&quot;highlight&quot;&gt;
Very useful for:
&lt;ul&gt;
&lt;li&gt;Hill Roads&lt;/li&gt;
&lt;li&gt;Remote Villages&lt;/li&gt;
&lt;li&gt;Bridge Projects&lt;/li&gt;
&lt;li&gt;Irrigation Works&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;21. JSON Export/Import&lt;/h2&gt;

&lt;pre&gt;
exportJSON()
importJSON()
&lt;/pre&gt;

&lt;p&gt;
Equivalent to:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estimate File Backup&lt;/li&gt;
&lt;li&gt;Project Sharing&lt;/li&gt;
&lt;li&gt;DPR Transfer Between Offices&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;22. Engineering Strengths&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Automated Rate Analysis&lt;/li&gt;
&lt;li&gt;Dynamic Material Consumption&lt;/li&gt;
&lt;li&gt;Material-wise Lead Calculation&lt;/li&gt;
&lt;li&gt;Offline Project Storage&lt;/li&gt;
&lt;li&gt;Reusable SSR Database&lt;/li&gt;
&lt;li&gt;Fast Quantity Revisions&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;23. Practical Civil Engineering Applications&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PWD Estimates&lt;/li&gt;
&lt;li&gt;MoRTH Road Projects&lt;/li&gt;
&lt;li&gt;Bridge Works&lt;/li&gt;
&lt;li&gt;Irrigation Estimates&lt;/li&gt;
&lt;li&gt;Building BOQs&lt;/li&gt;
&lt;li&gt;Tender Costing&lt;/li&gt;
&lt;li&gt;Contractor Billing&lt;/li&gt;
&lt;li&gt;DPR Preparation&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;24. Equivalent Commercial Software&lt;/h2&gt;

&lt;p&gt;
This code partially replicates features of:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PWD Estimate Software&lt;/li&gt;
&lt;li&gt;CivilMantra&lt;/li&gt;
&lt;li&gt;Candy&lt;/li&gt;
&lt;li&gt;CostX&lt;/li&gt;
&lt;li&gt;Excel-based DPR Systems&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;25. Final Engineering Interpretation&lt;/h2&gt;

&lt;div class=&quot;highlight&quot;&gt;
This software is a browser-based SSR-driven civil estimation engine integrating:
&lt;ul&gt;
&lt;li&gt;Material Consumption Analysis&lt;/li&gt;
&lt;li&gt;Lead Charge Interpolation&lt;/li&gt;
&lt;li&gt;Transportation Costing&lt;/li&gt;
&lt;li&gt;Abstract Preparation&lt;/li&gt;
&lt;li&gt;Persistent Project Management&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;p&gt;
In practical civil engineering terms, it automates the complete workflow from SSR item selection to final estimate abstract generation with realistic material transportation logistics.
&lt;/p&gt;

&lt;/div&gt;

&lt;script&gt;
let ssrData = [];
let leadData = [];
let estimateList = [];
let db;
window.materialLeads = {}; 

const request = indexedDB.open(&quot;PWDEstimateDB&quot;, 1);
request.onupgradeneeded = e =&gt; {
    db = e.target.result;
    db.createObjectStore(&quot;projects&quot;, { keyPath: &quot;name&quot; });
};
request.onsuccess = e =&gt; {
    db = e.target.result;
    refreshProjectList();
};
  
const SSR_CSV = &quot;https://docs.google.com/spreadsheets/d/e/2PACX-1vQ4kUoGLLSfoAc_0FAGlfiajGDhAOOd0oPI-I2F4-b21mm-IjOGP5dBNtHtRC97VJJZU17ZSWKWwfqm/pub?gid=0&amp;single=true&amp;output=csv&quot;;
const LEAD_CSV = &quot;https://docs.google.com/spreadsheets/d/e/2PACX-1vQ4kUoGLLSfoAc_0FAGlfiajGDhAOOd0oPI-I2F4-b21mm-IjOGP5dBNtHtRC97VJJZU17ZSWKWwfqm/pub?gid=860705186&amp;single=true&amp;output=csv&quot;;

// Lead CSV matching column letters (Matching image 1)
const materialMapping = {
    &quot;Murum&quot;: &#39;D&#39;, &quot;Earth / Soil&quot;: &#39;D&#39;, &quot;Rubble / Soling&quot;: &#39;H&#39;, 
    &quot;Natural Sand&quot;: &#39;J&#39;, &quot;Crush Sand&quot;: &#39;J&#39;, &quot;Metal Below 40 mm&quot;: &#39;J&#39;,
    &quot;40 mm &amp; Above&quot;: &#39;M&#39;, &quot;Cement&quot;: &#39;R&#39;, &quot;Bricks&quot;: &#39;T&#39;, 
    &quot;Flooring Tiles&quot;: &#39;V&#39;, &quot;Manglore Tiles&quot;: &#39;V&#39;, &quot;Steel&quot;: &#39;X&#39;
};

// SSR material consumption factor column letters (From &quot;SSR 22 23&quot; - Matching image 2)
const matColumns = {
    &quot;Cement&quot;: &#39;K&#39;, &quot;Natural Sand&quot;: &#39;L&#39;, &quot;Crush Sand&quot;: &#39;M&#39;, &quot;Metal Below 40 mm&quot;: &#39;N&#39;,
    &quot;Pipes&quot;: &#39;O&#39;, &quot;Steel&quot;: &#39;P&#39;, &quot;Murum&quot;: &#39;Q&#39;, &quot;Earth / Soil&quot;: &#39;R&#39;, &quot;Rubble / Soling&quot;: &#39;S&#39;,
    &quot;40 mm &amp; Above&quot;: &#39;T&#39;, &quot;Asphalt&quot;: &#39;U&#39;, &quot;Bricks&quot;: &#39;V&#39;, &quot;Concrete&quot;: &#39;W&#39;, &quot;GRIT&quot;: &#39;X&#39;,
    &quot;Flooring Tiles&quot;: &#39;Y&#39;, &quot;Glazed / Ceramic Tiles&quot;: &#39;Z&#39;, &quot;Natural Stone Flooring&quot;: &#39;AA&#39;,
    &quot;Manglore Tiles&quot;: &#39;AB&#39;
};

async function init() {
    try {
        const cacheBuster = `&amp;t=${new Date().getTime()}`;
        const [res1, res2] = await Promise.all([
            fetch(SSR_CSV + cacheBuster), 
            fetch(LEAD_CSV + cacheBuster)
        ]);
        
        if (!res1.ok || !res2.ok) throw new Error(&quot;Could not retrieve spreadsheet data.&quot;);

        const t1 = await res1.text();
        const t2 = await res2.text();

        Papa.parse(t1, { header: false, skipEmptyLines: true, complete: (r) =&gt; { ssrData = r.data; } });
        Papa.parse(t2, { header: false, skipEmptyLines: true, complete: (r) =&gt; {
            leadData = r.data;
            document.getElementById(&#39;status&#39;).innerText = &quot;System Ready - Data Loaded&quot;;
            document.getElementById(&#39;status&#39;).className = &quot;status-bar ready&quot;;
            document.getElementById(&#39;addBtn&#39;).disabled = false;
        }});
    } catch (e) {
        document.getElementById(&#39;status&#39;).innerText = &quot;Connection Failed: &quot; + e.message;
        document.getElementById(&#39;status&#39;).style.background = &quot;#f8d7da&quot;;
    }
}

function letterToIdx(letter) {
    let index = 0;
    const str = letter.toUpperCase();
    for (let i = 0; i &lt; str.length; i++) {
        index = index * 26 + str.charCodeAt(i) - 64;
    }
    return index - 1; 
}

function interpolateLead(dist, colLetter) {
    if (!leadData || leadData.length === 0 || isNaN(dist)) return 0;
    const colIdx = letterToIdx(colLetter);

    const sorted = leadData
        .map(row =&gt; {
            const kmVal = parseFloat(String(row[0]).trim());
            const rateVal = parseFloat(String(row[colIdx]).replace(/,/g, &#39;&#39;).trim()) || 0;
            return { km: kmVal, val: rateVal };
        })
        .filter(r =&gt; !isNaN(r.km))
        .sort((a, b) =&gt; a.km - b.km);

    if (sorted.length === 0) return 0;
    if (dist &lt;= sorted[0].km) return sorted[0].val;
    if (dist &gt;= sorted[sorted.length - 1].km) return sorted[sorted.length - 1].val;

    for (let i = 0; i &lt; sorted.length - 1; i++) {
        if (dist &gt;= sorted[i].km &amp;&amp; dist &lt;= sorted[i + 1].km) {
            const x1 = sorted[i].km, x2 = sorted[i + 1].km;
            const y1 = sorted[i].val, y2 = sorted[i + 1].val;
            if (x1 === x2) return y1;
            return y1 + ((dist - x1) * (y2 - y1) / (x2 - x1));
        }
    }
    return 0;
}

function addItem() {
    if (ssrData.length === 0) return alert(&quot;SSR data not loaded yet.&quot;);
    const searchInput = document.getElementById(&#39;itemSearch&#39;).value.trim();
    const qty = parseFloat(document.getElementById(&#39;itemQty&#39;).value) || 0;

    const item = ssrData.find(row =&gt; row &amp;&amp; String(row[2]).trim() === searchInput);
    if (item) {
        const clonedItem = [...item];
        clonedItem.inputQty = qty;
        estimateList.push(clonedItem);
        recalculateAll();
        document.getElementById(&#39;itemSearch&#39;).value = &quot;&quot;;
    } else {
        alert(`Item &quot;${searchInput}&quot; not found in SSR.`);
    }
}

function deleteItem(index) {
    if(confirm(&quot;Remove this item?&quot;)) {
        estimateList.splice(index, 1);
        recalculateAll();
    }
}

function editItem(index) {
    const newQty = prompt(&quot;Enter new Quantity:&quot;, estimateList[index].inputQty);
    if (newQty !== null) {
        estimateList[index].inputQty = parseFloat(newQty) || 0;
        recalculateAll();
    }
}

function saveToDB() {
    const name = document.getElementById(&#39;projectName&#39;).value.trim();
    if (!name) return alert(&quot;Please enter a Project Name&quot;);
    const transaction = db.transaction([&quot;projects&quot;], &quot;readwrite&quot;);
    transaction.objectStore(&quot;projects&quot;).put({
        name: name,
        estimateList: estimateList,
        materialLeads: window.materialLeads,
        settings: {
            lead: document.getElementById(&#39;leadDist&#39;).value,
            cess: document.getElementById(&#39;cessInput&#39;).value
        }
    });
    transaction.oncomplete = () =&gt; { alert(&quot;Project Saved Successfully!&quot;); refreshProjectList(); };
}

async function loadProject(name) {
    if (!name) return;
    const store = db.transaction([&quot;projects&quot;], &quot;readonly&quot;).objectStore(&quot;projects&quot;);
    store.get(name).onsuccess = e =&gt; {
        const p = e.target.result;
        estimateList = p.estimateList;
        window.materialLeads = p.materialLeads || {};
        document.getElementById(&#39;projectName&#39;).value = p.name;
        document.getElementById(&#39;leadDist&#39;).value = p.settings.lead;
        document.getElementById(&#39;cessInput&#39;).value = p.settings.cess;
        recalculateAll();
    };
}

function refreshProjectList() {
    const select = document.getElementById(&#39;projectList&#39;);
    const store = db.transaction([&quot;projects&quot;], &quot;readonly&quot;).objectStore(&quot;projects&quot;);
    select.innerHTML = &#39;&lt;option value=&quot;&quot;&gt;-- Load Saved Project --&lt;/option&gt;&#39;;
    store.openCursor().onsuccess = e =&gt; {
        const cursor = e.target.result;
        if (cursor) {
            const opt = document.createElement(&#39;option&#39;);
            opt.value = cursor.key; opt.textContent = cursor.key;
            select.appendChild(opt);
            cursor.continue();
        }
    };
}

function recalculateAll() {
    if (leadData.length === 0) return;

    const cessFact = parseFloat(document.getElementById(&#39;cessInput&#39;).value) / 100 || 0;
    const globalLead = parseFloat(document.getElementById(&#39;leadDist&#39;).value) || 0;
    let html = &quot;&quot;;
    let totalPartA = 0;
    let matTotals = {};
    for (let m in matColumns) matTotals[m] = 0;

    // Calculate dynamic total material consumptions (Item Qty * consumption factor)
    estimateList.forEach(item =&gt; {
        for (let m in matColumns) {
            const colIdx = letterToIdx(matColumns[m]);
            const factor = parseFloat(String(item[colIdx]).replace(/,/g, &#39;&#39;)) || 0;
            matTotals[m] += factor * item.inputQty;
        }
    });

    estimateList.forEach((item, index) =&gt; {
        const ssrRate = parseFloat(String(item[8]).replace(/,/g, &#39;&#39;)) || 0; 
        const netRate = ssrRate - (ssrRate * cessFact);
      	const areacostperc = parseFloat(document.getElementById(&#39;areaCharge&#39;).value) || 0;
      	const AreaCost = netRate * areacostperc/100
        
        let itemLeadCost = 0;
        for (let m in matColumns) {
            const colIdx = letterToIdx(matColumns[m]);
            const factor = parseFloat(String(item[colIdx]).replace(/,/g, &#39;&#39;)) || 0;
            
            if (factor &gt; 0 &amp;&amp; materialMapping[m]) {
                const specDist = window.materialLeads[m];
                const dist = (specDist !== undefined &amp;&amp; specDist !== &quot;&quot;) ? parseFloat(specDist) : globalLead;
                const leadRate = interpolateLead(dist, materialMapping[m]);
                itemLeadCost += (factor * leadRate);
            }
        }

        const finalRate = netRate + itemLeadCost + (ssrRate * cessFact) + AreaCost;
        const amount = finalRate * item.inputQty;
        totalPartA += (netRate * item.inputQty);

        html += `&lt;tr&gt;
            &lt;td&gt;${item[2] || &#39;N/A&#39;}&lt;/td&gt; 
            &lt;td title=&quot;${item[4] || &#39;&#39;}&quot;&gt;${(item[4] || &#39;N/A&#39;).substring(0,35)}...&lt;/td&gt;
            &lt;td&gt;${item[7] || &#39;N/A&#39;}&lt;/td&gt;
            &lt;td&gt;${item.inputQty}&lt;/td&gt;
            &lt;td&gt;${ssrRate.toFixed(2)}&lt;/td&gt;
            &lt;td&gt;${netRate.toFixed(2)}&lt;/td&gt;
            &lt;td style=&quot;color: #2980b9;&quot;&gt;${itemLeadCost.toFixed(2)}&lt;/td&gt;
            &lt;td&gt;&lt;strong&gt;${finalRate.toFixed(2)}&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;${amount.toFixed(2)}&lt;/td&gt;
            &lt;td&gt;
                &lt;button class=&quot;btn btn-edit&quot; onclick=&quot;editItem(${index})&quot;&gt;Edit&lt;/button&gt;
                &lt;button class=&quot;btn btn-delete&quot; onclick=&quot;deleteItem(${index})&quot;&gt;Del&lt;/button&gt;
            &lt;/td&gt;
        &lt;/tr&gt;`;
    });

    document.getElementById(&#39;tableBody&#39;).innerHTML = html;
    updateSummaries(totalPartA, matTotals);
}

function updateSummaries(partA, matTotals) {
    let matHtml = `&lt;table style=&quot;width:100%; font-size:11px; border-collapse:collapse;&quot;&gt;
        &lt;thead&gt;&lt;tr style=&quot;background:#eee;&quot;&gt;&lt;th&gt;Material&lt;/th&gt;&lt;th&gt;Consumption Qty&lt;/th&gt;&lt;th&gt;Lead (km)&lt;/th&gt;&lt;th&gt;Charges&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;`;
    
    let totalLeadAmount = 0;
    let found = false;
    const globalLead = parseFloat(document.getElementById(&#39;leadDist&#39;).value) || 0;

    for (let m in matTotals) {
        if (matTotals[m] &gt; 0) {
            let specDist = window.materialLeads[m];
            let dist = (specDist !== undefined &amp;&amp; specDist !== &quot;&quot;) ? parseFloat(specDist) : globalLead;
            let colLetter = materialMapping[m];
            let leadRate = (colLetter !== undefined) ? interpolateLead(dist, colLetter) : 0;
            let leadAmt = matTotals[m] * leadRate;
            totalLeadAmount += leadAmt;

            matHtml += `&lt;tr&gt;
                &lt;td&gt;${m}&lt;/td&gt;
                &lt;td&gt;&lt;strong&gt;${matTotals[m].toFixed(3)}&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;input type=&quot;number&quot; value=&quot;${dist}&quot; style=&quot;width:65px&quot; oninput=&quot;updateLeadDist(&#39;${m}&#39;, this.value)&quot;&gt;&lt;/td&gt;
                &lt;td&gt;₹${leadAmt.toFixed(2)}&lt;/td&gt;
            &lt;/tr&gt;`;
            found = true;
        }
    }

    document.getElementById(&#39;materialSummary&#39;).innerHTML = found ? matHtml + &quot;&lt;/tbody&gt;&lt;/table&gt;&quot; : &quot;No consumption.&quot;;
    
    const grandTotal = partA + totalLeadAmount;
    const gst = grandTotal * 0.18;
    document.getElementById(&#39;abstractSummary&#39;).innerHTML = `
        &lt;p&gt;Civil (Net): ₹${partA.toLocaleString(undefined, {minimumFractionDigits: 2})}&lt;/p&gt;
        &lt;p&gt;Total Lead: ₹${totalLeadAmount.toLocaleString(undefined, {minimumFractionDigits: 2})}&lt;/p&gt;
        &lt;p&gt;GST (18%): ₹${gst.toLocaleString(undefined, {minimumFractionDigits: 2})}&lt;/p&gt;
        &lt;hr&gt;&lt;h4&gt;Grand Total: ₹${(grandTotal + gst).toLocaleString(undefined, {minimumFractionDigits: 2})}&lt;/h4&gt;`;
}

function updateLeadDist(material, val) {
    window.materialLeads[material] = val;
    recalculateAll(); 
}

function exportJSON() {
    const data = JSON.stringify({
        project: document.getElementById(&#39;projectName&#39;).value,
        items: estimateList,
        materialLeads: window.materialLeads
    });
    const blob = new Blob([data], { type: &#39;application/json&#39; });
    const url = URL.createObjectURL(blob);
    const a = document.createElement(&#39;a&#39;);
    a.href = url;
    a.download = `${document.getElementById(&#39;projectName&#39;).value || &#39;Estimate&#39;}.json`;
    a.click();
}

function importJSON(event) {
    const reader = new FileReader();
    reader.onload = e =&gt; {
        try {
            const imported = JSON.parse(e.target.result);
            estimateList = imported.items || [];
            window.materialLeads = imported.materialLeads || {};
            if(imported.project) document.getElementById(&#39;projectName&#39;).value = imported.project;
            recalculateAll();
        } catch(err) { alert(&quot;Invalid JSON file&quot;); }
    };
    reader.readAsText(event.target.files[0]);
}

init();
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/05/estimate-calculation-tool-ssr-2022-23.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-2605591030278010824</guid><pubDate>Wed, 29 Apr 2026 12:16:32 +0000</pubDate><atom:updated>2026-05-14T17:44:01.750+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><title>Tentative Project schedule Generator</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js&quot;&gt;&lt;/script&gt;

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js&quot;&gt;&lt;/script&gt;
    &lt;title&gt;MoRTH Resource &amp; Machinery Planner&lt;/title&gt;
&lt;style&gt;
/* 1. BASE APP STYLES - Scoped to avoid Blogger conflicts */
#civil-scheduler {
    font-family: &#39;Segoe UI&#39;, Roboto, Helvetica, Arial, sans-serif;
    background: #fdfdfd;
    color: #2c3e50;
    line-height: 1.5;
}

#civil-scheduler .card {
    background: #ffffff;
    padding: 2px;
    border-radius: 10px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.05);
    border: 1px solid #eaeeef;
    margin-bottom: 20px;
}

#civil-scheduler h2 {
    margin: 0 0 20px 0;
    color: #1a3a83;
    font-size: 1.5rem;
    display: flex;
    align-items: center;
    gap: 10px;
}

/* 2. CONTROL PANEL */
#civil-scheduler .controls {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 2px;
    background: #f8f9fc;
    padding: 2px;
    border-radius: 8px;
    border: 1px solid #e3e6f0;
    margin-bottom: 5px;
}

#civil-scheduler .input-group label {
    display: block;
    font-weight: 600;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 6px;
    color: #4e73df;
}

#civil-scheduler input {
    width: 100%;
    padding: 2px;
    border: 1px solid #d1d3e2;
    border-radius: 5px;
    box-sizing: border-box;
}

#civil-scheduler button {
    background: #4e73df;
    color: white;
    border: none;
    border-radius: 5px;
    padding: 2px 2px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.3s ease;
    height: 42px;
    align-self: end;
}

#civil-scheduler button:hover {
    background: #2e59d9;
    transform: translateY(-1px);
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}

/* 3. TABLE STYLES */
#civil-scheduler .table-container {
    width: 100%;
    max-height: 1700px;
    overflow: auto;
    border: 1px solid #e3e6f0;
    border-radius: 8px;
    background: #fff;
}

#civil-scheduler table {
    width: 100%;
    min-width: 600px;
    border-collapse: collapse;
    font-size: 13px;
}

#civil-scheduler th {
    background: #4e73df;
    color: #ffffff;
    padding: 2px 2px;
    font-weight: 600;
    text-transform: uppercase;
    font-size: 11px;
    border: 1px solid #dbe2ef;
    text-align: center;
    position: sticky;
    top: 0;
    z-index: 5;
}

#civil-scheduler td {
    padding: 2px 2px;
    border: 1px solid #e3e6f0;
    background: #fff;
    vertical-align: middle;
}

#civil-scheduler .qty-input {
    width: 80px;
    padding: 2px;
    border: 1px solid #d1d3e2;
    text-align: center;
    font-weight: bold;
    color: #e74a3b;
}

#civil-scheduler .machine-badge {
    display: inline-block;
    background: #1cc88a;
    color: white;
    padding: 2px 2px;
    border-radius: 20px;
    font-size: 11px;
    font-weight: 700;
}

/* SCROLLBAR */
#civil-scheduler .table-container::-webkit-scrollbar,
.gantt-wrapper::-webkit-scrollbar {
    height: 10px;
    width: 10px;
}

#civil-scheduler .table-container::-webkit-scrollbar-thumb,
.gantt-wrapper::-webkit-scrollbar-thumb {
    background: #b8c2d6;
    border-radius: 10px;
}

/* 4. GANTT CHART STYLES */
.gantt-wrapper {
    margin-top: 30px;
    background: #fff;
    padding: 2px;
    border-radius: 8px;
    border: 1px solid #eaeeef;
    overflow: auto;
    max-height: 1700px;
}

.gantt-chart {
    display: grid;
    grid-template-columns: 250px 1fr;
    border: 1px solid #ddd;
    position: relative;
    min-width: 1600px;
    width: max-content;
}

.gantt-label {
    padding: 2px 2px;
    border-bottom: 1px solid #eee;
    background: #fdfdfd;
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.gantt-timeline {
    position: relative;
    height: 35px;
    border-bottom: 1px solid #eee;
    background-image: linear-gradient(
        to right,
        #f1f1f1 1px,
        transparent 1px
    );
    background-size: 5% 100%;
}

.gantt-bar {
    position: absolute;
    height: 16px;
    top: 9px;
    border-radius: 10px;
    background: #4e73df;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.monsoon-bar {
    background: #9b59b6 !important;
}

/* PDF EXPORT SAFE RULES */
.html2pdf__container,
.html2pdf__container * {
    box-sizing: border-box;
}

.html2pdf__container {
    background: #ffffff !important;
    color: #000000 !important;
    width: 100% !important;
    overflow: visible !important;
}

.html2pdf__container .controls,
.html2pdf__container button {
    display: none !important;
}

/* IMPORTANT: REMOVE SCROLL IN PDF */
.html2pdf__container .table-container {
    overflow: visible !important;
    max-height: none !important;
    height: auto !important;
}

.html2pdf__container .gantt-wrapper {
    overflow: visible !important;
    max-height: none !important;
    height: auto !important;
}

.html2pdf__container table {
    border-collapse: collapse !important;
    width: 100% !important;
    min-width: 1200px !important;
}

.html2pdf__container th,
.html2pdf__container td {
    border: 1px solid #d9d9d9 !important;
}

.html2pdf__container .gantt-chart {
    display: grid !important;
    grid-template-columns: 150px 1fr !important;
    min-width: 1600px !important;
    width: max-content !important;
}

/* Better rendering */
* {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
}

/* A3 Landscape */
@page {
    size: A3 landscape;
    margin: 10mm;
}
#civil-scheduler select {
    width: 100%;
    padding: 2px;
    border: 1px solid #d1d3e2;
    border-radius: 5px;
    box-sizing: border-box;
    background: #fff;
}
  .start-date,
.end-date{
    width:130px;
    padding:2px;
    border:1px solid #d1d3e2;
    border-radius:4px;
    font-size:11px;
}
  .highlight{
    background:#fff8e1;
    border-left:5px solid #ff9800;
    padding:14px;
    margin:15px 0;
}

.formula{
    background:#e8f5e9;
    border-left:5px solid #2e7d32;
    padding:14px;
    font-weight:bold;
    margin:15px 0;
}

.note{
    background:#e3f2fd;
    border-left:5px solid #1976d2;
    padding:14px;
    margin:15px 0;
}
  pre{
    background:#272822;
    color:#f8f8f2;
    padding:15px;
    overflow:auto;
    border-radius:6px;
}

code{
    background:#eef2f5;
    padding:2px 5px;
    border-radius:4px;
    color:#c62828;
}

&lt;/style&gt;
  
  &lt;/head&gt;
&lt;body&gt;

&lt;!-- In your Blogger HTML, wrap your content like this: --&gt;
&lt;div id=&quot;civil-scheduler&quot;&gt;
    &lt;div class=&quot;card&quot;&gt;
        &lt;h2&gt;🚧 Road Project Resource &amp; Machinery Planner&lt;/h2&gt;
      
      &lt;div class=&quot;input-group&quot;&gt;
    &lt;label&gt;Project Name&lt;/label&gt;
    &lt;input id=&quot;projectName&quot; type=&quot;text&quot; placeholder=&quot;Enter Project Name&quot;&gt;
&lt;/div&gt;

&lt;div class=&quot;input-group&quot;&gt;
    &lt;label&gt;Saved Projects&lt;/label&gt;
    &lt;select id=&quot;savedProjects&quot;&gt;
        &lt;option value=&quot;&quot;&gt;Select Project&lt;/option&gt;
    &lt;/select&gt;
&lt;/div&gt;
      
      

&lt;button onclick=&quot;saveProject()&quot;&gt;Save Project&lt;/button&gt;
&lt;button onclick=&quot;loadProject()&quot;&gt;Load Project&lt;/button&gt;
&lt;button onclick=&quot;deleteProject()&quot;&gt;Delete Project&lt;/button&gt;
        
        &lt;div class=&quot;controls&quot;&gt;
            &lt;div class=&quot;input-group&quot;&gt;
                &lt;label&gt;Work Order Date&lt;/label&gt;
                &lt;input id=&quot;woDate&quot; type=&quot;date&quot; onchange=&quot;regenerateProjectDates()&quot;&gt;
            &lt;/div&gt;
            &lt;div class=&quot;input-group&quot;&gt;
                &lt;label&gt;Project Length (km)&lt;/label&gt;
                &lt;input id=&quot;projLength&quot; step=&quot;0.1&quot; type=&quot;number&quot; value=&quot;10&quot; /&gt;
            &lt;/div&gt;
            &lt;div class=&quot;input-group&quot;&gt;
                &lt;label&gt;Duration (Days)&lt;/label&gt;
                &lt;input id=&quot;totalDuration&quot; type=&quot;number&quot; value=&quot;365&quot; /&gt;
            &lt;/div&gt;
            &lt;button onclick=&quot;generateSchedule()&quot;&gt;Generate Schedule&lt;/button&gt;
        &lt;/div&gt;

        &lt;div class=&quot;table-container&quot;&gt;
            &lt;table id=&quot;mainTable&quot;&gt;
                &lt;thead&gt;
                    &lt;tr&gt;
                        &lt;th style=&quot;min-width: 220px;&quot;&gt;Activity Description&lt;/th&gt;
                        &lt;th&gt;Quantity&lt;/th&gt;
                        &lt;th&gt;Unit&lt;/th&gt;
                        &lt;th&gt;Start Date&lt;/th&gt;
                        &lt;th&gt;End Date&lt;/th&gt;
                        &lt;th&gt;Days&lt;/th&gt;
                        &lt;th&gt;Machinery&lt;/th&gt;
                        &lt;th&gt;Output/Day&lt;/th&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody id=&quot;tbody&quot;&gt;
                    &lt;!-- JS will populate this --&gt;
                &lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
  
  &lt;div class=&quot;gantt-wrapper&quot;&gt;
    &lt;h3&gt;Timeline Visualization&lt;/h3&gt;
    &lt;div id=&quot;ganttChart&quot; class=&quot;gantt-chart&quot;&gt;
        &lt;!-- JS will populate this --&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;button onclick=&quot;downloadPDF()&quot; style=&quot;background:#1cc88a;&quot;&gt;Download A3 PDF&lt;/button&gt;
  
  &lt;div class=&quot;container&quot;&gt;

&lt;h1&gt;Road Project Resource &amp; Machinery Planner – Civil Engineering Perspective&lt;/h1&gt;

&lt;p&gt;
This code is an advanced &lt;strong&gt;Road Construction Planning and Scheduling System&lt;/strong&gt;
developed for civil engineering projects.
&lt;/p&gt;

&lt;p&gt;
It automates:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project Scheduling&lt;/li&gt;
&lt;li&gt;Road Construction Planning&lt;/li&gt;
&lt;li&gt;Machinery Requirement Analysis&lt;/li&gt;
&lt;li&gt;Resource Allocation&lt;/li&gt;
&lt;li&gt;Timeline Visualization&lt;/li&gt;
&lt;li&gt;Gantt Chart Generation&lt;/li&gt;
&lt;li&gt;Project Monitoring&lt;/li&gt;
&lt;li&gt;PDF Reporting&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;1. Purpose of the Software&lt;/h2&gt;

&lt;p&gt;
This software behaves like a digital:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Construction Planning Cell&lt;/li&gt;
&lt;li&gt;Project Monitoring Unit (PMU)&lt;/li&gt;
&lt;li&gt;Road Execution Scheduler&lt;/li&gt;
&lt;li&gt;Machinery Deployment Planner&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Engineering Activity&lt;/th&gt;
&lt;th&gt;Code Function&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Project Scheduling&lt;/td&gt;
&lt;td&gt;&lt;code&gt;generateSchedule()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Machinery Planning&lt;/td&gt;
&lt;td&gt;&lt;code&gt;updateResources()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Duration Analysis&lt;/td&gt;
&lt;td&gt;&lt;code&gt;updateDuration()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Timeline Visualization&lt;/td&gt;
&lt;td&gt;&lt;code&gt;drawGantt()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;PDF Report Generation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;downloadPDF()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Project Saving&lt;/td&gt;
&lt;td&gt;&lt;code&gt;saveProject()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;hr&gt;

&lt;h2&gt;2. Main User Interface&lt;/h2&gt;

&lt;pre&gt;
&amp;lt;div id=&quot;civil-scheduler&quot;&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
This is the complete project planning dashboard.
&lt;/p&gt;

&lt;p&gt;
The interface allows engineers to:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create projects&lt;/li&gt;
&lt;li&gt;Generate schedules&lt;/li&gt;
&lt;li&gt;Manage timelines&lt;/li&gt;
&lt;li&gt;Calculate machinery requirements&lt;/li&gt;
&lt;li&gt;Export reports&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;3. Project Information Inputs&lt;/h2&gt;

&lt;pre&gt;
&amp;lt;input id=&quot;projectName&quot;&amp;gt;
&amp;lt;input id=&quot;woDate&quot;&amp;gt;
&amp;lt;input id=&quot;projLength&quot;&amp;gt;
&amp;lt;input id=&quot;totalDuration&quot;&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;Engineering Meaning&lt;/h3&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Engineering Purpose&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Project Name&lt;/td&gt;
&lt;td&gt;Identification of road work&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Work Order Date&lt;/td&gt;
&lt;td&gt;Project commencement reference&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Project Length&lt;/td&gt;
&lt;td&gt;Total road length in km&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Duration&lt;/td&gt;
&lt;td&gt;Total contractual period&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;div class=&quot;highlight&quot;&gt;
Equivalent to:
&lt;ul&gt;
&lt;li&gt;Work Program Register&lt;/li&gt;
&lt;li&gt;Contract Agreement Data&lt;/li&gt;
&lt;li&gt;Construction Time Schedule&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;4. IndexedDB Project Storage&lt;/h2&gt;

&lt;pre&gt;
const request = indexedDB.open(&quot;MoRTHPlannerDB&quot;, 1);
&lt;/pre&gt;

&lt;p&gt;
Creates a local browser database for storing projects.
&lt;/p&gt;

&lt;h3&gt;Engineering Interpretation&lt;/h3&gt;

&lt;p&gt;
Acts like:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digital DPR Archive&lt;/li&gt;
&lt;li&gt;Construction Schedule Register&lt;/li&gt;
&lt;li&gt;Project Monitoring Database&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;5. Saving Projects&lt;/h2&gt;

&lt;pre&gt;
function saveProject()
&lt;/pre&gt;

&lt;p&gt;
Stores:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project Details&lt;/li&gt;
&lt;li&gt;Schedule Table&lt;/li&gt;
&lt;li&gt;Gantt Chart&lt;/li&gt;
&lt;li&gt;Timeline Data&lt;/li&gt;
&lt;li&gt;Resource Calculations&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;note&quot;&gt;
Equivalent to saving:
&lt;ul&gt;
&lt;li&gt;CPM Charts&lt;/li&gt;
&lt;li&gt;Bar Charts&lt;/li&gt;
&lt;li&gt;Construction Programs&lt;/li&gt;
&lt;li&gt;Project Planning Reports&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;6. Project Loading &amp; Deletion&lt;/h2&gt;

&lt;pre&gt;
loadProject()
deleteProject()
&lt;/pre&gt;

&lt;p&gt;
Allows:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening saved construction schedules&lt;/li&gt;
&lt;li&gt;Revising project plans&lt;/li&gt;
&lt;li&gt;Removing old schedules&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;7. Schedule Generation Engine&lt;/h2&gt;

&lt;pre&gt;
function generateSchedule()
&lt;/pre&gt;

&lt;p&gt;
This is the core planning engine of the software.
&lt;/p&gt;

&lt;h3&gt;Engineering Purpose&lt;/h3&gt;

&lt;p&gt;
Automatically generates:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Construction Activities&lt;/li&gt;
&lt;li&gt;Start Dates&lt;/li&gt;
&lt;li&gt;End Dates&lt;/li&gt;
&lt;li&gt;Machinery Deployment&lt;/li&gt;
&lt;li&gt;Execution Sequence&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;8. Activity Template&lt;/h2&gt;

&lt;pre&gt;
const activityTemplate = [
[&quot;Earthwork (Embankment/Subgrade)&quot;, 0.12, 0.50, &quot;cum&quot;, 300]
]
&lt;/pre&gt;

&lt;h3&gt;Engineering Interpretation&lt;/h3&gt;

&lt;p&gt;
Each activity contains:
&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Activity Name&lt;/td&gt;
&lt;td&gt;Construction Operation&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Start Fraction&lt;/td&gt;
&lt;td&gt;Project Start Position&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;End Fraction&lt;/td&gt;
&lt;td&gt;Project Completion Position&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Unit&lt;/td&gt;
&lt;td&gt;Measurement Unit&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Output Rate&lt;/td&gt;
&lt;td&gt;Daily Machinery Productivity&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;hr&gt;

&lt;h2&gt;9. Pre-Construction Activities&lt;/h2&gt;

&lt;p&gt;
The software includes planning activities such as:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DPR Preparation&lt;/li&gt;
&lt;li&gt;Forest Clearance&lt;/li&gt;
&lt;li&gt;Utility Shifting&lt;/li&gt;
&lt;li&gt;Land Acquisition&lt;/li&gt;
&lt;li&gt;Tender Process&lt;/li&gt;
&lt;li&gt;Agreement Execution&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;
This makes the software highly realistic for:
&lt;ul&gt;
&lt;li&gt;MoRTH Projects&lt;/li&gt;
&lt;li&gt;PWD Road Works&lt;/li&gt;
&lt;li&gt;EPC Contracts&lt;/li&gt;
&lt;li&gt;BOT Highway Projects&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;10. Construction Activities&lt;/h2&gt;

&lt;p&gt;
The software includes actual field construction operations:
&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Activity&lt;/th&gt;
&lt;th&gt;Engineering Work&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Earthwork&lt;/td&gt;
&lt;td&gt;Formation &amp; Embankment&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;GSB&lt;/td&gt;
&lt;td&gt;Granular Sub Base&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;WMM&lt;/td&gt;
&lt;td&gt;Wet Mix Macadam&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;DBM&lt;/td&gt;
&lt;td&gt;Dense Bituminous Macadam&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;PQC&lt;/td&gt;
&lt;td&gt;Pavement Quality Concrete&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;BC/SDBC&lt;/td&gt;
&lt;td&gt;Bituminous Wearing Course&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;hr&gt;

&lt;h2&gt;11. Automatic Quantity Estimation&lt;/h2&gt;

&lt;pre&gt;
const getQty = (name) =&gt; {
    if(name.includes(&quot;Embankment&quot;))
        return km * 4500;
}
&lt;/pre&gt;

&lt;p&gt;
The software estimates quantities automatically using road length.
&lt;/p&gt;

&lt;h3&gt;Engineering Meaning&lt;/h3&gt;

&lt;p&gt;
Example:
&lt;/p&gt;

&lt;div class=&quot;formula&quot;&gt;
Earthwork Quantity = Road Length × Standard Earthwork Factor
&lt;/div&gt;

&lt;p&gt;
For a 10 km road:
&lt;/p&gt;

&lt;div class=&quot;formula&quot;&gt;
Earthwork = 10 × 4500 = 45,000 cum
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;12. Unit Determination Logic&lt;/h2&gt;

&lt;pre&gt;
getUnit()
&lt;/pre&gt;

&lt;p&gt;
Automatically assigns engineering units:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cum → Earthwork&lt;/li&gt;
&lt;li&gt;sqm → Pavement Layers&lt;/li&gt;
&lt;li&gt;m → Drainage&lt;/li&gt;
&lt;li&gt;nos → Structures&lt;/li&gt;
&lt;li&gt;Ha → Forest Clearance&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;13. Dynamic Date Generation&lt;/h2&gt;

&lt;pre&gt;
addDays()
formatDate()
&lt;/pre&gt;

&lt;p&gt;
Automatically calculates:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Activity Start Date&lt;/li&gt;
&lt;li&gt;Activity End Date&lt;/li&gt;
&lt;li&gt;Total Duration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Engineering Significance&lt;/h3&gt;

&lt;p&gt;
Equivalent to:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPM Scheduling&lt;/li&gt;
&lt;li&gt;PERT Planning&lt;/li&gt;
&lt;li&gt;Bar Chart Planning&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;14. Monsoon Adjustment Logic&lt;/h2&gt;

&lt;pre&gt;
if (task[0].includes(&quot;Bituminous&quot;))
&lt;/pre&gt;

&lt;p&gt;
This is one of the most important engineering features.
&lt;/p&gt;

&lt;p&gt;
The software detects:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bituminous activities during monsoon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
and automatically postpones them.
&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;
Engineering Reason:
&lt;ul&gt;
&lt;li&gt;Bituminous works should not be executed during heavy rainfall&lt;/li&gt;
&lt;li&gt;Moisture affects compaction&lt;/li&gt;
&lt;li&gt;Rain damages hot mix quality&lt;/li&gt;
&lt;li&gt;Temperature control becomes difficult&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;p&gt;
This reflects actual site engineering practice.
&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;15. Machinery Requirement Calculation&lt;/h2&gt;

&lt;pre&gt;
machinesNeeded = qty / (dur × stdRate)
&lt;/pre&gt;

&lt;div class=&quot;formula&quot;&gt;
Machinery Sets Required =
Quantity ÷ (Available Days × Daily Production)
&lt;/div&gt;

&lt;h3&gt;Example&lt;/h3&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Earthwork Quantity&lt;/td&gt;
&lt;td&gt;45,000 cum&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Duration&lt;/td&gt;
&lt;td&gt;50 Days&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Excavator Output&lt;/td&gt;
&lt;td&gt;300 cum/day&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;div class=&quot;formula&quot;&gt;
Machines Needed =
45000 ÷ (50 × 300)
= 3 Sets
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;16. Resource Warning System&lt;/h2&gt;

&lt;pre&gt;
badge.style.background =
(machinesNeeded &gt; 15)
&lt;/pre&gt;

&lt;p&gt;
If machinery requirement becomes excessive:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System shows warning color&lt;/li&gt;
&lt;li&gt;Indicates unrealistic planning&lt;/li&gt;
&lt;li&gt;Suggests schedule revision&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;17. Duration Update Logic&lt;/h2&gt;

&lt;pre&gt;
updateDuration()
&lt;/pre&gt;

&lt;p&gt;
If engineer changes dates:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duration recalculates automatically&lt;/li&gt;
&lt;li&gt;Machinery requirements update instantly&lt;/li&gt;
&lt;li&gt;Gantt chart refreshes automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;18. Gantt Chart Generation&lt;/h2&gt;

&lt;pre&gt;
drawGantt()
drawEditableGantt()
&lt;/pre&gt;

&lt;p&gt;
This generates a visual construction timeline.
&lt;/p&gt;

&lt;h3&gt;Engineering Meaning&lt;/h3&gt;

&lt;p&gt;
Equivalent to:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MS Project Charts&lt;/li&gt;
&lt;li&gt;Primavera Schedules&lt;/li&gt;
&lt;li&gt;Construction Bar Charts&lt;/li&gt;
&lt;li&gt;Highway Execution Programs&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;19. Timeline Header&lt;/h2&gt;

&lt;pre&gt;
month:&#39;short&#39;,
year:&#39;2-digit&#39;
&lt;/pre&gt;

&lt;p&gt;
The software automatically creates:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monthly Progress Timeline&lt;/li&gt;
&lt;li&gt;Year-wise Schedule Markers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Example:
&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Timeline&lt;/th&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Jan-26&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Feb-26&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Mar-26&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;hr&gt;

&lt;h2&gt;20. Gantt Bars&lt;/h2&gt;

&lt;pre&gt;
bar.style.left
bar.style.width
&lt;/pre&gt;

&lt;p&gt;
These determine:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Activity start position&lt;/li&gt;
&lt;li&gt;Activity duration&lt;/li&gt;
&lt;li&gt;Execution overlap&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Engineering Interpretation&lt;/h3&gt;

&lt;p&gt;
Allows engineers to visualize:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Critical activities&lt;/li&gt;
&lt;li&gt;Parallel operations&lt;/li&gt;
&lt;li&gt;Project sequencing&lt;/li&gt;
&lt;li&gt;Resource conflicts&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;21. Editable Scheduling&lt;/h2&gt;

&lt;p&gt;
When engineers manually edit dates:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schedule updates dynamically&lt;/li&gt;
&lt;li&gt;Resources recalculate&lt;/li&gt;
&lt;li&gt;Timeline regenerates&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;note&quot;&gt;
Equivalent to live project planning in:
&lt;ul&gt;
&lt;li&gt;Primavera P6&lt;/li&gt;
&lt;li&gt;MS Project&lt;/li&gt;
&lt;li&gt;TILOS&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;hr&gt;

&lt;h2&gt;22. PDF Report Generation&lt;/h2&gt;

&lt;pre&gt;
downloadPDF()
&lt;/pre&gt;

&lt;p&gt;
Generates:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A3 Project Schedule&lt;/li&gt;
&lt;li&gt;Printable Gantt Charts&lt;/li&gt;
&lt;li&gt;Construction Planning Reports&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Engineering Importance&lt;/h3&gt;

&lt;p&gt;
Useful for:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Review Meetings&lt;/li&gt;
&lt;li&gt;Progress Monitoring&lt;/li&gt;
&lt;li&gt;Client Submission&lt;/li&gt;
&lt;li&gt;Authority Approvals&lt;/li&gt;
&lt;li&gt;Site Execution Planning&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;23. Automatic File Naming&lt;/h2&gt;

&lt;pre&gt;
Road_Project_2026-05-14.pdf
&lt;/pre&gt;

&lt;p&gt;
The system automatically:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds Project Name&lt;/li&gt;
&lt;li&gt;Adds Date&lt;/li&gt;
&lt;li&gt;Creates organized documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;24. Engineering Strengths of This Software&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Realistic Construction Sequencing&lt;/li&gt;
&lt;li&gt;Automatic Machinery Planning&lt;/li&gt;
&lt;li&gt;Monsoon-sensitive Scheduling&lt;/li&gt;
&lt;li&gt;Dynamic Resource Allocation&lt;/li&gt;
&lt;li&gt;Editable Gantt Charts&lt;/li&gt;
&lt;li&gt;Automatic Quantity Estimation&lt;/li&gt;
&lt;li&gt;Project Database Storage&lt;/li&gt;
&lt;li&gt;A3 PDF Reporting&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;25. Practical Applications&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;MoRTH Highway Projects&lt;/li&gt;
&lt;li&gt;PWD Road Works&lt;/li&gt;
&lt;li&gt;Rural Roads&lt;/li&gt;
&lt;li&gt;Expressways&lt;/li&gt;
&lt;li&gt;Bridge Approach Roads&lt;/li&gt;
&lt;li&gt;Urban Roads&lt;/li&gt;
&lt;li&gt;Industrial Corridor Projects&lt;/li&gt;
&lt;li&gt;EPC Contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;26. Equivalent Commercial Software&lt;/h2&gt;

&lt;p&gt;
This code partially replicates features of:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primavera P6&lt;/li&gt;
&lt;li&gt;MS Project&lt;/li&gt;
&lt;li&gt;TILOS&lt;/li&gt;
&lt;li&gt;Asta Powerproject&lt;/li&gt;
&lt;li&gt;Candy Construction Planning&lt;/li&gt;
&lt;/ul&gt;

&lt;hr&gt;

&lt;h2&gt;27. Final Engineering Interpretation&lt;/h2&gt;

&lt;div class=&quot;highlight&quot;&gt;
This software is a browser-based road construction planning and machinery deployment system integrating:
&lt;ul&gt;
&lt;li&gt;Construction Scheduling&lt;/li&gt;
&lt;li&gt;Road Activity Sequencing&lt;/li&gt;
&lt;li&gt;Resource Planning&lt;/li&gt;
&lt;li&gt;Machinery Analysis&lt;/li&gt;
&lt;li&gt;Timeline Visualization&lt;/li&gt;
&lt;li&gt;Gantt Chart Monitoring&lt;/li&gt;
&lt;li&gt;Project Archiving&lt;/li&gt;
&lt;li&gt;PDF Reporting&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;p&gt;
In practical civil engineering terms, this software automates the complete workflow from project initiation to construction scheduling, machinery deployment, and progress visualization for road infrastructure projects.
&lt;/p&gt;

&lt;/div&gt;
  
  
&lt;script&gt;
  
  let db;

const request = indexedDB.open(&quot;MoRTHPlannerDB&quot;, 1);

request.onupgradeneeded = function(e) {

    db = e.target.result;

    if (!db.objectStoreNames.contains(&quot;projects&quot;)) {

        db.createObjectStore(&quot;projects&quot;, {
            keyPath: &quot;name&quot;
        });

    }
};

request.onsuccess = function(e) {

    db = e.target.result;

    refreshProjectList();
};

request.onerror = function() {

    alert(&quot;IndexedDB failed&quot;);
};

function saveProject() {

    const projectName =
        document.getElementById(&quot;projectName&quot;).value.trim();

    if (!projectName) {

        alert(&quot;Enter Project Name&quot;);
        return;
    }

    const projectData = {

        name: projectName,

        woDate:
            document.getElementById(&quot;woDate&quot;).value,

        projLength:
            document.getElementById(&quot;projLength&quot;).value,

        totalDuration:
            document.getElementById(&quot;totalDuration&quot;).value,

        tableHTML:
            document.getElementById(&quot;tbody&quot;).innerHTML,

        ganttHTML:
            document.getElementById(&quot;ganttChart&quot;).innerHTML,

        savedAt:
            new Date().toISOString()
    };

    const tx = db.transaction(
        [&quot;projects&quot;],
        &quot;readwrite&quot;
    );

    const store = tx.objectStore(&quot;projects&quot;);

    store.put(projectData);

    tx.oncomplete = function() {

        alert(&quot;Project Saved&quot;);

        refreshProjectList();
    };
}

function refreshProjectList() {

    const dropdown =
        document.getElementById(&quot;savedProjects&quot;);

    dropdown.innerHTML =
        &#39;&lt;option value=&quot;&quot;&gt;Select Project&lt;/option&gt;&#39;;

    const tx =
        db.transaction([&quot;projects&quot;], &quot;readonly&quot;);

    const store =
        tx.objectStore(&quot;projects&quot;);

    const request =
        store.getAll();

    request.onsuccess = function() {

        request.result.forEach(project =&gt; {

            const option =
                document.createElement(&quot;option&quot;);

            option.value = project.name;

            option.textContent = project.name;

            dropdown.appendChild(option);
        });
    };
}

function loadProject() {

    const projectName =
        document.getElementById(&quot;savedProjects&quot;).value;

    if (!projectName) {

        alert(&quot;Select Project&quot;);
        return;
    }

    const tx =
        db.transaction([&quot;projects&quot;], &quot;readonly&quot;);

    const store =
        tx.objectStore(&quot;projects&quot;);

    const request =
        store.get(projectName);

    request.onsuccess = function() {

        const data = request.result;

        if (!data) return;

        document.getElementById(&quot;projectName&quot;).value =
            data.name;

        document.getElementById(&quot;woDate&quot;).value =
            data.woDate;

        document.getElementById(&quot;projLength&quot;).value =
            data.projLength;

        document.getElementById(&quot;totalDuration&quot;).value =
            data.totalDuration;

        document.getElementById(&quot;tbody&quot;).innerHTML =
            data.tableHTML;

        document.getElementById(&quot;ganttChart&quot;).innerHTML =
            data.ganttHTML;

        restoreRowEvents();
      
      regenerateGanttFromTable();

        alert(&quot;Project Loaded&quot;);
    };
}

function deleteProject() {

    const projectName =
        document.getElementById(&quot;savedProjects&quot;).value;

    if (!projectName) {

        alert(&quot;Select Project&quot;);
        return;
    }

    if (!confirm(&quot;Delete Project?&quot;)) return;

    const tx =
        db.transaction([&quot;projects&quot;], &quot;readwrite&quot;);

    const store =
        tx.objectStore(&quot;projects&quot;);

    store.delete(projectName);

    tx.oncomplete = function() {

        refreshProjectList();

        alert(&quot;Project Deleted&quot;);
    };
}

function restoreRowEvents() {

    document
    .querySelectorAll(&quot;.qty-input&quot;)
    .forEach(input =&gt; {

        input.oninput = function() {

            updateResources(
                this.parentElement.parentElement
            );
        };
    });

    document
    .querySelectorAll(&quot;.start-date, .end-date&quot;)
    .forEach(input =&gt; {

        input.onchange = function() {

            updateDuration(
                this.parentElement.parentElement
            );
        };
    });
}
  
function addDays(date, days) {
    let d = new Date(date);
    d.setDate(d.getDate() + days);
    return d;
}

function formatDate(d) {
    return d.toLocaleDateString(&#39;en-GB&#39;).replace(/\//g, &#39;-&#39;);
}

function generateSchedule() {
    const woInput = document.getElementById(&quot;woDate&quot;).value;
    if (!woInput) { alert(&quot;Please select a Work Order Date&quot;); return; }
    
    const wo = new Date(woInput);
    const km = parseFloat(document.getElementById(&quot;projLength&quot;).value) || 0;
    const totalProjDays = parseInt(document.getElementById(&quot;totalDuration&quot;).value) || 365;
    const tbody = document.getElementById(&quot;tbody&quot;);
    tbody.innerHTML = &quot;&quot;;

    let scheduleData = []; // To store data for Gantt

    const activityTemplate = [
        [&quot;DPR Preparation including costing&quot;, -0.45, -0.35, &quot;Job&quot;, 0.05],
        [&quot;DPR Approval&quot;, -0.35, -0.28, &quot;Job&quot;, 0.1],
        [&quot;Administrative and Financial approval&quot;, -0.28, -0.20, &quot;Job&quot;, 0.1],
        [&quot;Forest Clearance (Tree Cutting/ROW)&quot;, -0.25, -0.02, &quot;Ha&quot;, 0.2],
        [&quot;Utility Clearance (MJP/Irrigation/EB)&quot;, -0.20, -0.05, &quot;km&quot;, 0.1],
        [&quot;Statutory Clearance (CRZ/NGT/Railway)&quot;, -0.25, -0.02, &quot;Job&quot;, 0.02],
        [&quot;Land Acquisition/Transfer&quot;, -0.30, -0.05, &quot;Ha&quot;, 0.1],
        [&quot;Encroachment Removal&quot;, -0.15, -0.05, &quot;km&quot;, 0.2],
        [&quot;Preparation of Bid Document&quot;, -0.25, -0.20, &quot;Job&quot;, 0.2],
        [&quot;Tender Publication &amp; Submission&quot;, -0.20, -0.12, &quot;Job&quot;, 0.05],
        [&quot;Technical &amp; Financial Evaluation&quot;, -0.12, -0.06, &quot;Job&quot;, 0.1],
        [&quot;LOA Issuance &amp; Acceptance&quot;, -0.06, -0.03, &quot;Job&quot;, 0.2],
        [&quot;Agreement &amp; Security Deposit&quot;, -0.03, -0.01, &quot;Job&quot;, 0.2],
        [&quot;Work Order Issuance&quot;, 0.00, 0.00, &quot;Date&quot;, 1],
        [&quot;Project Kick start &amp; Deployment&quot;, 0.01, 0.05, &quot;Job&quot;, 0.1],
        [&quot;Retaining Wall / Toe Wall&quot;, 0.05, 0.40, &quot;cum&quot;, 14], 
        [&quot;Culverts (New/Repair)&quot;, 0.08, 0.60, &quot;nos&quot;, 0.1],
        [&quot;RCC Box Drain / Pipe Drain&quot;, 0.10, 0.70, &quot;m&quot;, 25],
        [&quot;Clearing and Grubbing&quot;, 0.02, 0.20, &quot;Ha&quot;, 0.5],
        [&quot;Earthwork (Embankment/Subgrade)&quot;, 0.12, 0.50, &quot;cum&quot;, 300],
        [&quot;Sub-Base Course (GSB)&quot;, 0.25, 0.65, &quot;cum&quot;, 36],
        [&quot;Non Bituminous Base Course (WMM)&quot;, 0.40, 0.75, &quot;cum&quot;, 200],
        [&quot;Bituminous Base Course (DBM)&quot;, 0.55, 0.90, &quot;sqm&quot;, 640],
        [&quot;Pavement Quality Concrete (PQC)&quot;, 0.50, 0.90, &quot;cum&quot;, 14],
        [&quot;Bituminous Wearing Course (BC/SDBC)&quot;, 0.80, 0.98, &quot;sqm&quot;, 760],
        [&quot;Side Shoulders&quot;, 0.85, 0.99, &quot;sqm&quot;, 500],
        [&quot;RCC Cover Slab Drain&quot;, 0.60, 0.90, &quot;m&quot;, 30],
        [&quot;Junction Development&quot;, 0.70, 0.95, &quot;nos&quot;, 0.1],
        [&quot;Bus Shelter &amp; Toilet Blocks&quot;, 0.50, 0.90, &quot;nos&quot;, 0.05],
        [&quot;Crash Barrier&quot;, 0.80, 0.98, &quot;m&quot;, 50],
        [&quot;Traffic Signs &amp; Gantry&quot;, 0.90, 1.00, &quot;nos&quot;, 2],
        [&quot;Road Marking&quot;, 0.92, 1.00, &quot;sqm&quot;, 400],
        [&quot;Solar Lights / Blinkers&quot;, 0.90, 1.00, &quot;nos&quot;, 5],
        [&quot;Km Stones &amp; Finishing&quot;, 0.95, 1.00, &quot;nos&quot;, 2]
    ];

    const getQty = (name) =&gt; {
        if(name.includes(&quot;Embankment&quot;)) return km * 4500;
        if(name.includes(&quot;GSB&quot;)) return km * 2500;
        if(name.includes(&quot;WMM&quot;)) return km * 2000;
        if(name.includes(&quot;Bituminous&quot;)) return km * 7000;
        if(name.includes(&quot;PQC&quot;)) return km * 2200;
        if(name.includes(&quot;Retaining&quot;)) return km * 150;
        if(name.includes(&quot;RCC Box Drain&quot;)) return km * 1000;
        if(name.includes(&quot;Forest&quot;)) return km * 0.8;
        if(name.includes(&quot;Land Acquisition&quot;)) return km * 1.5;
        if(name.includes(&quot;Clearing and Grubbing&quot;)) return km * 0.7;
        if(name.includes(&quot;Cover Slab Drain&quot;)) return km * 500;
        if(name.includes(&quot;Crash Barrier&quot;)) return km * 200;
        if(name.includes(&quot;Marking&quot;)) return km * 150;
        if(name.includes(&quot;Utility&quot;) || name.includes(&quot;Encroachment&quot;)) return km;
        if(name.includes(&quot;Junction&quot;)) return 4;
        if(name.includes(&quot;Bus Shelter&quot;)) return 2;
        return 1;
    }

    const getUnit = (name) =&gt; {
        if(name.includes(&quot;sqm&quot;) || name.includes(&quot;Bituminous&quot;) || name.includes(&quot;Marking&quot;) || name.includes(&quot;Shoulders&quot;)) return &quot;sqm&quot;;
        if(name.includes(&quot;cum&quot;) || name.includes(&quot;Earthwork&quot;) || name.includes(&quot;Base Course&quot;) || name.includes(&quot;PQC&quot;) || name.includes(&quot;Wall&quot;)) return &quot;cum&quot;;
        if(name.includes(&quot;nos&quot;) || name.includes(&quot;Culverts&quot;) || name.includes(&quot;Junction&quot;) || name.includes(&quot;Shelter&quot;) || name.includes(&quot;Km Stones&quot;)) return &quot;nos&quot;;
        if(name.includes(&quot;Ha&quot;) || name.includes(&quot;Forest&quot;) || name.includes(&quot;Clearing&quot;)) return &quot;Ha&quot;;
        if(name.includes(&quot;m&quot;) || name.includes(&quot;Drain&quot;) || name.includes(&quot;Barrier&quot;)) return &quot;m&quot;;
        if(name.includes(&quot;km&quot;)) return &quot;km&quot;;
        return &quot;Job&quot;;
    }

    activityTemplate.forEach((task) =&gt; {
        let row = tbody.insertRow();
        let startDays = Math.round(task[1] * totalProjDays);
        let endDays = Math.round(task[2] * totalProjDays);
        let workDuration = Math.max(1, endDays - startDays);
        
        let sDate = addDays(wo, startDays);
        let eDate = addDays(wo, endDays);
        let isMonsoon = false;

        if (task[0].includes(&quot;Bituminous&quot;) &amp;&amp; !task[0].includes(&quot;Non&quot;)) {
            if (sDate.getMonth() &gt;= 5 &amp;&amp; sDate.getMonth() &lt;= 8) {
                sDate = new Date(sDate.getFullYear(), 9, 1);
                eDate = addDays(sDate, workDuration);
                isMonsoon = true;
            }
        }

        row.innerHTML = `
            &lt;td style=&quot;text-align:left&quot;&gt;${task[0]}&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;number&quot; class=&quot;qty-input&quot; value=&quot;${Math.round(getQty(task[0]))}&quot; oninput=&quot;updateResources(this.parentElement.parentElement)&quot;&gt;&lt;/td&gt;
            &lt;td&gt;${getUnit(task[0])}&lt;/td&gt;
            &lt;td&gt;
    &lt;input 
        type=&quot;date&quot; 
        class=&quot;start-date&quot; 
        value=&quot;${sDate.toISOString().split(&#39;T&#39;)[0]}&quot;
        onchange=&quot;updateDuration(this.parentElement.parentElement)&quot;
    &gt;
&lt;/td&gt;

&lt;td&gt;
    &lt;input 
        type=&quot;date&quot; 
        class=&quot;end-date&quot; 
        value=&quot;${eDate.toISOString().split(&#39;T&#39;)[0]}&quot;
        onchange=&quot;updateDuration(this.parentElement.parentElement)&quot;
    &gt;
&lt;/td&gt;
            &lt;td class=&quot;dur-val&quot;&gt;${workDuration}&lt;/td&gt;
            &lt;td&gt;&lt;span class=&quot;machine-badge&quot;&gt;--&lt;/span&gt;&lt;/td&gt;
            &lt;td class=&quot;std-out&quot;&gt;${task[4]}&lt;/td&gt;
        `;
        row.dataset.mRate = task[4];
        updateResources(row);

        // Save data for Gantt
        scheduleData.push({
            name: task[0],
            start: startDays,
            end: startDays + workDuration,
            isMonsoon: isMonsoon
        });
    });

    drawGantt(scheduleData, totalProjDays);
}

function updateResources(row) {
    const qty = parseFloat(row.querySelector(&#39;.qty-input&#39;).value) || 0;
    const dur = parseInt(row.querySelector(&#39;.dur-val&#39;).innerText) || 1;
    const stdRate = parseFloat(row.dataset.mRate);

    // Engineering Formula: Quantity / (Available Days * Machine Production)
    let machinesNeeded = Math.ceil(qty / (dur * stdRate));
    
    const badge = row.querySelector(&#39;.machine-badge&#39;);
    badge.innerText = machinesNeeded + (machinesNeeded &gt; 1 ? &quot; Sets&quot; : &quot; Set&quot;);
    
    // UI Warning if resources are too high
    badge.style.background = (machinesNeeded &gt; 15) ? &quot;#eb4d4b&quot; : &quot;#20bf6b&quot;;
}
  
function updateDuration(row) {

    const startVal =
        row.querySelector(&quot;.start-date&quot;).value;

    const endVal =
        row.querySelector(&quot;.end-date&quot;).value;

    if (!startVal || !endVal) return;

    // Safe date parsing
    const start = new Date(startVal + &quot;T00:00:00&quot;);
    const end = new Date(endVal + &quot;T00:00:00&quot;);

    let diff =
        Math.ceil(
            (end - start) /
            (1000 * 60 * 60 * 24)
        );

    if (diff &lt; 1) diff = 1;

    row.querySelector(&quot;.dur-val&quot;).innerText = diff;

    updateResources(row);

    // IMPORTANT → Refresh Gantt
    regenerateGanttFromTable();
}
  
  function regenerateGanttFromTable() {

    const rows =
        document.querySelectorAll(&quot;#tbody tr&quot;);

    const ganttData = [];

    let minDate = null;
    let maxDate = null;

    rows.forEach(row =&gt; {

        const task =
            row.cells[0].innerText;

        const startVal =
            row.querySelector(&quot;.start-date&quot;).value;

        const endVal =
            row.querySelector(&quot;.end-date&quot;).value;

        if (!startVal || !endVal) return;

        const start =
            new Date(startVal + &quot;T00:00:00&quot;);

        const end =
            new Date(endVal + &quot;T00:00:00&quot;);

        if (!minDate || start &lt; minDate)
            minDate = start;

        if (!maxDate || end &gt; maxDate)
            maxDate = end;

        ganttData.push({
            name: task,
            startDate: start,
            endDate: end
        });
    });

    drawEditableGantt(ganttData, minDate, maxDate);
}
  
function drawEditableGantt(data, minDate, maxDate) {

    const chart =
        document.getElementById(&quot;ganttChart&quot;);

    chart.innerHTML = &quot;&quot;;

    const totalRange =
        Math.ceil(
            (maxDate - minDate) /
            (1000 * 60 * 60 * 24)
        );

    // Header spacer
    const spacer = document.createElement(&quot;div&quot;);
    spacer.style.background = &quot;#4e73df&quot;;
    chart.appendChild(spacer);

    // Timeline Header
    const header = document.createElement(&quot;div&quot;);

    header.style.cssText =
        &quot;position:relative;height:30px;background:#4e73df;color:white;font-size:10px;font-weight:bold;&quot;;

    let current =
        new Date(minDate);

    current.setDate(1);

    while (current &lt;= maxDate) {

        const tick =
            document.createElement(&quot;div&quot;);

        const offset =
            (current - minDate) /
            (1000 * 60 * 60 * 24);

        const left =
            (offset / totalRange) * 100;

        tick.style.cssText =
            `position:absolute;
             left:${left}%;
             border-left:1px solid rgba(255,255,255,0.3);
             height:100%;
             padding-left:4px;
             display:flex;
             align-items:center;`;

        tick.innerText =
            current.toLocaleString(
                &#39;default&#39;,
                {
                    month:&#39;short&#39;,
                    year:&#39;2-digit&#39;
                }
            );

        header.appendChild(tick);

        current.setMonth(current.getMonth() + 1);
    }

    chart.appendChild(header);

    // Tasks
    data.forEach(task =&gt; {

        const label =
            document.createElement(&quot;div&quot;);

        label.className = &quot;gantt-label&quot;;

        label.innerText = task.name;

        const timeline =
            document.createElement(&quot;div&quot;);

        timeline.className = &quot;gantt-timeline&quot;;

        const bar =
            document.createElement(&quot;div&quot;);

        bar.className = &quot;gantt-bar&quot;;

        const left =
            ((task.startDate - minDate) /
            (1000 * 60 * 60 * 24) /
            totalRange) * 100;

        const width =
            ((task.endDate - task.startDate) /
            (1000 * 60 * 60 * 24) /
            totalRange) * 100;

        bar.style.left = left + &quot;%&quot;;

        bar.style.width =
            Math.max(0.5, width) + &quot;%&quot;;

        timeline.appendChild(bar);

        chart.appendChild(label);

        chart.appendChild(timeline);
    });
}
  
function drawGantt(data, totalDays) {
    const chart = document.getElementById(&quot;ganttChart&quot;);
    chart.innerHTML = &quot;&quot;;
    const woDate = new Date(document.getElementById(&quot;woDate&quot;).value);

    const minStart = Math.min(...data.map(d =&gt; d.start));
    const maxEnd = Math.max(...data.map(d =&gt; d.end));
    const range = maxEnd - minStart;

    // Create Date Header
    const spacer = document.createElement(&quot;div&quot;);
    spacer.style.background = &quot;#4e73df&quot;;
    chart.appendChild(spacer);

    const header = document.createElement(&quot;div&quot;);
    header.style.cssText = &quot;position:relative; height:30px; background:#4e73df; color:white; font-size:10px; font-weight:bold;&quot;;
    
    let current = addDays(woDate, minStart);
    current.setDate(1); // Align to start of month
    const end = addDays(woDate, maxEnd);

    while (current &lt;= end) {
        const tick = document.createElement(&quot;div&quot;);
        const offset = (current - addDays(woDate, minStart)) / (1000*60*60*24);
        const left = (offset / range) * 100;
        
        if (left &gt;= 0 &amp;&amp; left &lt; 100) {
            tick.style.cssText = `position:absolute; left:${left}%; border-left:1px solid rgba(255,255,255,0.3); height:100%; padding-left:4px; display:flex; align-items:center;`;
            tick.innerText = current.toLocaleString(&#39;default&#39;, { month: &#39;short&#39;, year: &#39;2-digit&#39; });
            header.appendChild(tick);
        }
        current.setMonth(current.getMonth() + 1);
    }
    chart.appendChild(header);

    // Render Task Rows
    data.forEach(task =&gt; {
        const label = document.createElement(&quot;div&quot;);
        label.className = &quot;gantt-label&quot;;
        label.innerText = task.name;

        const timeline = document.createElement(&quot;div&quot;);
        timeline.className = &quot;gantt-timeline&quot;;

        const bar = document.createElement(&quot;div&quot;);
        bar.className = &quot;gantt-bar&quot; + (task.isMonsoon ? &quot; monsoon-bar&quot; : &quot;&quot;);
        const left = ((task.start - minStart) / range) * 100;
        const width = ((task.end - task.start) / range) * 100;

        bar.style.left = left + &quot;%&quot;;
        bar.style.width = Math.max(0.5, width) + &quot;%&quot;;
        
        timeline.appendChild(bar);
        chart.appendChild(label);
        chart.appendChild(timeline);
    });
}
  
async function downloadPDF() {
  
  if (
    !document.getElementById(&quot;tbody&quot;).innerHTML.trim()
) {
    alert(&quot;Generate Schedule First&quot;);
    return;
}

    const element = document.createElement(&quot;div&quot;);

    element.style.background = &quot;#ffffff&quot;;
    element.style.padding = &quot;20px&quot;;
    element.style.width = &quot;1600px&quot;;

    const title = document.createElement(&quot;h2&quot;);
  
    const projectName =
    document.getElementById(&quot;projectName&quot;).value ||
    &quot;Road Project&quot;;

title.innerText =
    projectName + &quot; - Project Schedule &amp; Gantt Chart&quot;;
  
    title.style.color = &quot;#1a3a83&quot;;
    title.style.marginBottom = &quot;20px&quot;;

    element.appendChild(title);

    element.appendChild(
        document.querySelector(&quot;#civil-scheduler&quot;).cloneNode(true)
    );

    element.appendChild(
        document.querySelector(&quot;.gantt-wrapper&quot;).cloneNode(true)
    );

    document.body.appendChild(element);

    try {

        await new Promise(r =&gt; setTimeout(r, 1500));

        const canvas = await html2canvas(element, {
            scale: 2,
            useCORS: true,
            backgroundColor: &quot;#ffffff&quot;,
            logging: false,
            scrollX: 0,
            scrollY: 0
        });

        const imgData = canvas.toDataURL(&quot;image/jpeg&quot;, 1.0);

        const { jsPDF } = window.jspdf;

        const pdf = new jsPDF({
            orientation: &quot;landscape&quot;,
            unit: &quot;mm&quot;,
            format: &quot;a3&quot;
        });

        const pageWidth = 420;
        const pageHeight = 297;

        const imgWidth = pageWidth;

        const imgHeight = (canvas.height * imgWidth) / canvas.width;

        let heightLeft = imgHeight;

        let position = 0;

        // First page
        pdf.addImage(
            imgData,
            &quot;JPEG&quot;,
            0,
            position,
            imgWidth,
            imgHeight
        );

        heightLeft -= pageHeight;

        // Additional pages
        while (heightLeft &gt; 0) {

            position = heightLeft - imgHeight;

            pdf.addPage();

            pdf.addImage(
                imgData,
                &quot;JPEG&quot;,
                0,
                position,
                imgWidth,
                imgHeight
            );

            heightLeft -= pageHeight;
        }

        // Project Name + Date based PDF filename
const projectName = document.getElementById(&quot;projectName&quot;)?.value || &quot;Road_Project&quot;;

const today = new Date();

const fileDate =
    today.getFullYear() + &quot;-&quot; +
    String(today.getMonth() + 1).padStart(2, &quot;0&quot;) + &quot;-&quot; +
    String(today.getDate()).padStart(2, &quot;0&quot;);

// Remove invalid filename characters
const safeProjectName = projectName
    .replace(/[&lt;&gt;:&quot;/\\|?*]+/g, &quot;&quot;)
    .replace(/\s+/g, &quot;_&quot;);

pdf.save(`${safeProjectName}_${fileDate}.pdf`);

    } catch(err) {

        console.error(err);

        alert(&quot;PDF generation failed&quot;);

    } finally {

        document.body.removeChild(element);

    }
}
  
  function regenerateProjectDates() {

    generateSchedule();

    saveProject();
}
&lt;/script&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/04/tentative-project-schedule-generator.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-6913654534010114015</guid><pubDate>Wed, 29 Apr 2026 06:58:52 +0000</pubDate><atom:updated>2026-06-17T19:37:25.288+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Design calculations</category><category domain="http://www.blogger.com/atom/ns#">Drawings</category><category domain="http://www.blogger.com/atom/ns#">Roads</category><title>Road cross section Generator</title><description>&lt;div style=&quot;font-family:Arial,Helvetica,sans-serif;margin:18px;color:#111&quot;&gt;
  &lt;h2&gt;Road Volume &amp; Earthwork (Cut/Fill) Calculator (9-Point Level Display)&lt;/h2&gt;

  &lt;div class=&quot;controls&quot; style=&quot;max-width:1200px&quot;&gt;
    &lt;div class=&quot;row&quot; style=&quot;display:flex;gap:8px;margin-bottom:10px;&quot;&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;
        &lt;label&gt;&lt;strong&gt;Pavement Type (Top Surface):&lt;/strong&gt;&lt;/label&gt;
        &lt;select id=&quot;pavementType&quot; style=&quot;font-size:13px;padding:6px;margin:6px 0;width:100%;box-sizing:border-box;font-weight:bold;&quot;&gt;
          &lt;option value=&quot;BT&quot;&gt;Bituminous Road (Smooth Parabolic Top)&lt;/option&gt;
          &lt;option value=&quot;CC&quot;&gt;Concrete Road (Straight Cross Slope Top)&lt;/option&gt;
        &lt;/select&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;label&gt;Paste Survey Data (Northing, Easting, Center-Line Design Z, **Optional OGL Z**) — one point per line:&lt;/label&gt;
    &lt;span style=&quot;font-size:11px;color:#555;display:block;margin-bottom:4px;&quot;&gt;Format: Northing, Easting, Design_Z, OGL_Z&lt;/span&gt;
    &lt;textarea id=&quot;surveyData&quot; style=&quot;font-size:13px;padding:6px;margin:6px 0;width:100%;box-sizing:border-box;height:80px;&quot; placeholder=&quot;2240951.477,342861.386,603.258,602.850\n2240959.020,342870.115,603.241,603.500&quot;&gt;&lt;/textarea&gt;

    &lt;div class=&quot;row&quot; style=&quot;display:flex;gap:8px&quot;&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;
        &lt;label&gt;Road Width (m)&lt;/label&gt;
        &lt;input id=&quot;roadWidth&quot; type=&quot;number&quot; value=&quot;7&quot; step=&quot;0.01&quot; min=&quot;0.01&quot; style=&quot;font-size:13px;padding:6px;margin:6px 0;width:100%;box-sizing:border-box&quot;&gt;
      &lt;/div&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;
        &lt;label&gt;Start Chainage (m)&lt;/label&gt;
        &lt;input id=&quot;startChainage&quot; type=&quot;number&quot; value=&quot;0&quot; step=&quot;0.01&quot; style=&quot;font-size:13px;padding:6px;margin:6px 0;width:100%;box-sizing:border-box&quot;&gt;
      &lt;/div&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;
        &lt;label&gt;Random Seed&lt;/label&gt;
        &lt;input id=&quot;randomSeed&quot; type=&quot;number&quot; value=&quot;12345&quot; style=&quot;font-size:13px;padding:6px;margin:6px 0;width:100%;box-sizing:border-box&quot;&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;row&quot; style=&quot;display:flex;gap:8px&quot;&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;
        &lt;label&gt;Base Layer Thickness Variation ± (%)&lt;/label&gt;
        &lt;input id=&quot;variation&quot; type=&quot;number&quot; value=&quot;10&quot; step=&quot;0.1&quot; min=&quot;0&quot; style=&quot;font-size:13px;padding:6px;margin:6px 0;width:100%;box-sizing:border-box&quot;&gt;
      &lt;/div&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;
        &lt;label&gt;Number of Layers&lt;/label&gt;
        &lt;input id=&quot;numLayers&quot; type=&quot;number&quot; value=&quot;3&quot; min=&quot;1&quot; style=&quot;font-size:13px;padding:6px;margin:6px 0;width:100%;box-sizing:border-box&quot;&gt;
      &lt;/div&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;
        &lt;label&gt;Design Speed (km/h)&lt;/label&gt;
        &lt;input id=&quot;designSpeed&quot; type=&quot;number&quot; value=&quot;80&quot; step=&quot;5&quot; style=&quot;font-size:13px;padding:6px;margin:6px 0;width:100%;box-sizing:border-box&quot;&gt;
      &lt;/div&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1;align-self:end&quot;&gt;
        &lt;button class=&quot;btn&quot; onclick=&quot;buildLayerRows()&quot; style=&quot;font-size:13px;padding:8px 12px;margin-right:8px;width:auto&quot;&gt;Build Layer Inputs&lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div id=&quot;layerInputs&quot;&gt;&lt;/div&gt;

    &lt;div class=&quot;row&quot; style=&quot;display:flex;gap:8px;margin-top:10px;&quot;&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;&lt;button class=&quot;btn&quot; onclick=&quot;parseSurvey()&quot; style=&quot;font-size:13px;padding:8px 12px;margin-right:8px;width:100%&quot;&gt;Parse Survey Data&lt;/button&gt;&lt;/div&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;&lt;button class=&quot;btn&quot; onclick=&quot;calculate()&quot; style=&quot;font-size:13px;padding:8px 12px;margin-right:8px;width:100%&quot;&gt;Calculate Crust &amp; Earthwork&lt;/button&gt;&lt;/div&gt;
      &lt;div class=&quot;col&quot; style=&quot;flex:1&quot;&gt;&lt;button class=&quot;btn&quot; id=&quot;downloadPdfBtn&quot; style=&quot;font-size:13px;padding:8px 12px;margin-right:8px;width:100%&quot;&gt;Export All (PDF)&lt;/button&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;Chainage-wise Cross Sections &amp; Data Sheets&lt;/h3&gt;
  &lt;div id=&quot;resultsContainer&quot;&gt;&lt;/div&gt;

  &lt;h3&gt;Consolidated Summary Abstract&lt;/h3&gt;
  &lt;div id=&quot;summaryContainer&quot; class=&quot;summary&quot; style=&quot;background:#f7f7f7;padding:10px;border-radius:6px;display:block !important;visibility:visible !important;min-height:50px&quot;&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;style&gt;
  table { border-collapse:collapse;width:100%;margin:8px 0;font-size:11px;display:table !important;visibility:visible !important }
  th, td { border:1px solid #bbb;padding:4px;text-align:center }
  .chainage-block { border:1px solid #ddd;padding:8px;margin:12px 0;border-radius:6px }
  canvas { border:1px solid #aaa;background:#fff }
  .summary { background:#f7f7f7 !important;padding:10px !important;border-radius:6px !important;display:block !important;visibility:visible !important;min-height:50px !important }
&lt;/style&gt;

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js&quot;&gt;&lt;/script&gt;

&lt;script&gt;
document.addEventListener(&#39;DOMContentLoaded&#39;, function() {
  let surveyPoints = [];
  let layers = [];
  let chainages = [];
  let perChainResults = {};

  function buildLayerRows(){
    const n = Math.max(1, parseInt(document.getElementById(&#39;numLayers&#39;)?.value||1));
    const cont = document.getElementById(&#39;layerInputs&#39;);
    if (!cont) return;
    cont.innerHTML = &#39;&#39;;
    for(let i=0; i&lt;n; i++){
      const div = document.createElement(&#39;div&#39;);
      div.style.border=&#39;1px solid #ddd&#39;; div.style.padding=&#39;8px&#39;; div.style.margin=&#39;6px 0&#39;;
      div.innerHTML = `
        &lt;strong&gt;Layer ${i+1} ${i===0 ? &#39;(Wearing Course)&#39; : &#39;(Sub-base/Base)&#39;}&lt;/strong&gt;
        &lt;div style=&quot;display:flex;gap:8px;margin-top:6px&quot;&gt;
          &lt;div style=&quot;flex:1&quot;&gt;&lt;label&gt;Type&lt;/label&gt;&lt;select class=&quot;layerName&quot;&gt;
            &lt;option ${i===0?&#39;selected&#39;:&#39;&#39;}&gt;BC&lt;/option&gt;
            &lt;option&gt;PQC&lt;/option&gt;
            &lt;option ${i===1?&#39;selected&#39;:&#39;&#39;}&gt;DBM&lt;/option&gt;
            &lt;option&gt;WMM&lt;/option&gt;
            &lt;option ${i===2?&#39;selected&#39;:&#39;&#39;}&gt;GSB&lt;/option&gt;
          &lt;/select&gt;&lt;/div&gt;
          &lt;div style=&quot;flex:1&quot;&gt;&lt;label&gt;Thickness (mm)&lt;/label&gt;&lt;input class=&quot;layerThk&quot; type=&quot;number&quot; value=&quot;${i===0?40:i===1?50:100}&quot; step=&quot;0.1&quot; min=&quot;0.1&quot;&gt;&lt;/div&gt;
          &lt;div style=&quot;flex:1&quot;&gt;&lt;label&gt;Camber (%)&lt;/label&gt;&lt;input class=&quot;layerCamber&quot; type=&quot;number&quot; value=&quot;2.5&quot; step=&quot;0.01&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;
      `;
      cont.appendChild(div);
    }
  }

  function parseSurvey(){
    surveyPoints = []; chainages = []; perChainResults = {};
    const raw = document.getElementById(&#39;surveyData&#39;)?.value.trim();
    if(!raw){ alert(&#39;Paste survey points first&#39;); return; }
    const lines = raw.split(/\r?\n/).map(s=&gt;s.trim()).filter(Boolean);
    let ch = parseFloat(document.getElementById(&#39;startChainage&#39;)?.value||0);
    let prev = null;
    
    for(let i=0; i&lt;lines.length; i++){
      const parts = lines[i].split(/[\t,; ]+/).filter(Boolean);
      if(parts.length&lt;3) { alert(`Invalid survey structure at line ${i+1}`); return; }
      
      const N = parseFloat(parts[0]); 
      const E = parseFloat(parts[1]); 
      const Z_Design = parseFloat(parts[2]);
      const Z_Ogl = parts[3] ? parseFloat(parts[3]) : (Z_Design - 0.50);

      if(prev){ ch += Math.hypot(N-prev.N, E-prev.E); }
      surveyPoints.push({N, E, Z: Z_Design, OGL: Z_Ogl, chain: ch});
      chainages.push(ch);
      prev = {N,E};
    }
    alert(`Successfully parsed ${surveyPoints.length} profile chainage nodes.`);
  }

  function seededRandom(seed){
    let t = Math.imul(seed += 0x6D2B79F5, 1 | seed);
    t = Math.imul(t ^ t &gt;&gt;&gt; 15, t | 1);
    return (((t ^ t &gt;&gt;&gt; 14) &gt;&gt;&gt; 0) / 4294967296);
  }

  function calculate(){
    if(surveyPoints.length&lt;2){ alert(&#39;Parse survey first&#39;); return; }
    const names = Array.from(document.querySelectorAll(&#39;.layerName&#39;)).map(el=&gt;el.value);
    const thks_mm = Array.from(document.querySelectorAll(&#39;.layerThk&#39;)).map(el=&gt;parseFloat(el.value||0));
    const camb = Array.from(document.querySelectorAll(&#39;.layerCamber&#39;)).map(el=&gt;parseFloat(el.value||0));
    layers = names.map((n,i)=&gt;({name:n, thk_m: (thks_mm[i]||0.1)/1000, camber_pct: (camb[i]||0)}));
    
    const width = parseFloat(document.getElementById(&#39;roadWidth&#39;)?.value) || 7;
    const varPct = parseFloat(document.getElementById(&#39;variation&#39;)?.value||10)/100;
    const seedBase = parseInt(document.getElementById(&#39;randomSeed&#39;)?.value||12345);
    const roadType = document.getElementById(&#39;pavementType&#39;).value;

    const numOffsets = 9; 
    const halfW = width / 2;
    const offsetPositions = [];
    for (let o = 0; o &lt; numOffsets; o++) {
      offsetPositions.push(-halfW + (o * (width / (numOffsets - 1))));
    }

    for(let i=0; i&lt;surveyPoints.length; i++){
      const p = surveyPoints[i];
      const topLevels = [];
      let activeUpperSurfaceZ = [];

      for(let li=0; li&lt;layers.length; li++){
        const baseNominalThk = layers[li].thk_m;
        let cam = layers[li].camber_pct/100;
        let layerTops = [];
        let layerBottoms = [];

        for (let o = 0; o &lt; numOffsets; o++) {
          const x = offsetPositions[o];
          let zTop = p.Z;

          if (li === 0) {
            if (roadType === &#39;BT&#39;) {
              zTop = p.Z - (2 * cam * Math.pow(x, 2)) / width;
            } else {
              zTop = p.Z - Math.abs(x) * cam;
            }
          } else {
            zTop = activeUpperSurfaceZ[o];
          }

          const rNode = seededRandom(seedBase + (i+1)*1000 + (li+1)*73 + o*17);
          const appliedVar = (li === 0) ? 0 : (rNode * 2 - 1) * varPct; 
          const calculatedThk = baseNominalThk * (1 + appliedVar);
          let zBot = zTop - calculatedThk;
          
          layerTops.push({x, z: zTop});
          layerBottoms.push({x, z: zBot});
        }
        topLevels.push({layerName: layers[li].name, tops: layerTops, bottoms: layerBottoms});
        activeUpperSurfaceZ = layerBottoms.map(b =&gt; b.z);
      }

      let oglProfile = [];
      for (let o = 0; o &lt; numOffsets; o++) {
        const x = offsetPositions[o];
        const terrainNoise = seededRandom(seedBase + (i+1)*500 + o*31) * 0.04 - 0.02;
        let zOgl = p.OGL + terrainNoise; 
        oglProfile.push({x, z: zOgl});
      }

      perChainResults[p.chain] = {chain: p.chain, levels: topLevels, oglProfile: oglProfile, offsets: offsetPositions};
    }

    // Calculations
    const areaAtChain = {}; const earthworkAtChain = {};
    chainages.forEach(ch =&gt; { areaAtChain[ch] = []; earthworkAtChain[ch] = {cut: 0, fill: 0}; });
    
    for(let i=0; i&lt;chainages.length; i++){
      const ch = chainages[i]; const rec = perChainResults[ch];
      for(let li=0; li&lt;layers.length; li++){
        let layerArea = 0;
        for(let o=0; o&lt;numOffsets-1; o++){
          const dX = rec.levels[li].tops[o+1].x - rec.levels[li].tops[o].x;
          const hL = rec.levels[li].tops[o].z - rec.levels[li].bottoms[o].z;
          const hR = rec.levels[li].tops[o+1].z - rec.levels[li].bottoms[o+1].z;
          layerArea += ((hL + hR) / 2) * dX;
        }
        areaAtChain[ch].push(layerArea);
      }
      const dsb = rec.levels[layers.length - 1].bottoms; const ogl = rec.oglProfile;
      let cutArea = 0; let fillArea = 0;
      for(let o=0; o&lt;numOffsets-1; o++){
        const dX = dsb[o+1].x - dsb[o].x;
        const dL = dsb[o].z - ogl[o].z; const dR = dsb[o+1].z - ogl[o+1].z;
        if (dL &gt;= 0 &amp;&amp; dR &gt;= 0) fillArea += ((dL + dR) / 2) * dX;
        else if (dL &lt;= 0 &amp;&amp; dR &lt;= 0) cutArea += (Math.abs(dL) + Math.abs(dR)) / 2 * dX;
        else {
          const ratio = Math.abs(dL) / (Math.abs(dL) + Math.abs(dR));
          const dX_intersect = dX * ratio;
          if (dL &gt;= 0) { fillArea += (dL / 2) * dX_intersect; cutArea += (Math.abs(dR) / 2) * (dX - dX_intersect); }
          else { cutArea += (Math.abs(dL) / 2) * dX_intersect; fillArea += (dR / 2) * (dX - dX_intersect); }
        }
      }
      earthworkAtChain[ch] = {cut: cutArea, fill: fillArea};
      rec.areas = areaAtChain[ch]; rec.earthwork = earthworkAtChain[ch];
    }

    const crustVolumes = Array(layers.length).fill(0).map(()=&gt;({total:0}));
    let totalCutVol = 0; let totalFillVol = 0;
    for(let si=0; si&lt;chainages.length-1; si++){
      const len = chainages[si+1] - chainages[si];
      for(let li=0; li&lt;layers.length; li++) crustVolumes[li].total += ((areaAtChain[chainages[si]][li] + areaAtChain[chainages[si+1]][li]) / 2) * len;
      totalCutVol += ((earthworkAtChain[chainages[si]].cut + earthworkAtChain[chainages[si+1]].cut) / 2) * len;
      totalFillVol += ((earthworkAtChain[chainages[si]].fill + earthworkAtChain[chainages[si+1]].fill) / 2) * len;
    }
    perChainResults._volumes = crustVolumes; perChainResults._earthworkTotal = {cut: totalCutVol, fill: totalFillVol};

    renderResults();
    renderSummary();
  }

  function renderResults(){
    const container = document.getElementById(&#39;resultsContainer&#39;);
    if (!container) return; container.innerHTML = &#39;&#39;;
    
    chainages.forEach((ch, idx)=&gt;{
      const rec = perChainResults[ch];
      const div = document.createElement(&#39;div&#39;); div.className=&#39;chainage-block&#39;; div.id = &#39;chainage-block-&#39;+idx;
      div.innerHTML = `&lt;h4&gt;Chainage ${ch.toFixed(3)}&lt;/h4&gt;`;
      
      // BUILD COMPLETE 9-POINT COMPREHENSIVE INTERMEDIATE LEVEL TABLES
      let tableHtml = `&lt;table&gt;
        &lt;tr style=&quot;background:#f2f2f2;&quot;&gt;
          &lt;th&gt;Target Layer Line&lt;/th&gt;
          ${rec.offsets.map(of =&gt; `&lt;th&gt;Offset&lt;br&gt;${of.toFixed(2)}m&lt;/th&gt;`).join(&#39;&#39;)}
          &lt;th&gt;Area (m²)&lt;/th&gt;
        &lt;/tr&gt;`;

      // Top Crust Face Row
      tableHtml += `&lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;Top Surface (Crust) Z&lt;/strong&gt;&lt;/td&gt;
        ${rec.levels[0].tops.map(t =&gt; `&lt;td&gt;${t.z.toFixed(3)}&lt;/td&gt;`).join(&#39;&#39;)}
        &lt;td rowspan=&quot;${layers.length + 2}&quot; style=&quot;background:#f4f8ff; font-weight:bold; vertical-align:middle;&quot;&gt;
          ${layers.map((l, li) =&gt; `${l.name}: ${rec.areas[li].toFixed(3)}`).join(&#39;&lt;br&gt;&lt;hr style=&quot;border:0;border-top:1px solid #ddd;&quot;&gt;&#39;)}
        &lt;/td&gt;
      &lt;/tr&gt;`;

      // Layer Bottom Base Intermediary Levels Rows
      for(let li=0; li&lt;layers.length; li++){
        tableHtml += `&lt;tr&gt;
          &lt;td&gt;Bottom of Layer ${li+1} (&lt;strong&gt;${rec.levels[li].layerName}&lt;/strong&gt;)&lt;/td&gt;
          ${rec.levels[li].bottoms.map(b =&gt; `&lt;td&gt;${b.z.toFixed(3)}&lt;/td&gt;`).join(&#39;&#39;)}
        &lt;/tr&gt;`;
      }

      // Natural OGL Row Line
      tableHtml += `&lt;tr style=&quot;background:#fffcf2;&quot;&gt;
        &lt;td&gt;&lt;strong&gt;OGL Profile Level Z&lt;/strong&gt;&lt;/td&gt;
        ${rec.oglProfile.map(o =&gt; `&lt;td&gt;${o.z.toFixed(3)}&lt;/td&gt;`).join(&#39;&#39;)}
        &lt;td style=&quot;font-weight:bold; font-size:10px; text-align:left;&quot;&gt;
          &lt;span style=&quot;color:#b22222;&quot;&gt;Cut: ${rec.earthwork.cut.toFixed(3)}&lt;/span&gt;&lt;br&gt;
          &lt;span style=&quot;color:#006400;&quot;&gt;Fill: ${rec.earthwork.fill.toFixed(3)}&lt;/span&gt;
        &lt;/td&gt;
      &lt;/tr&gt;&lt;/table&gt;`;

      const tblWrap = document.createElement(&#39;div&#39;); tblWrap.innerHTML = tableHtml;
      div.appendChild(tblWrap);

      // Render structural sheet canvas graph element
      const canvas = document.createElement(&#39;canvas&#39;); canvas.width = 780; canvas.height = 450;
      canvas.id = &#39;cs_&#39;+idx; canvas.style.display=&#39;block&#39;; canvas.style.margin=&#39;8px auto&#39;;
      div.appendChild(canvas);
      container.appendChild(div);
      drawCrossSectionAt(ch, &#39;cs_&#39;+idx);
    });
  }

  function drawCrossSectionAt(chain, canvasId){
    const rec = perChainResults[chain]; if(!rec) return;
    const canvas = document.getElementById(canvasId); if(!canvas) return;
    const ctx = canvas.getContext(&#39;2d&#39;); ctx.clearRect(0,0,canvas.width,canvas.height);
    
    const W = parseFloat(document.getElementById(&#39;roadWidth&#39;)?.value) || 7;
    const ys = [];
    rec.levels.forEach(lvl=&gt;{ lvl.tops.forEach(t =&gt; ys.push(t.z)); lvl.bottoms.forEach(b =&gt; ys.push(b.z)); });
    rec.oglProfile.forEach(o =&gt; ys.push(o.z));
    
    const minY = Math.min(...ys), maxY = Math.max(...ys);
    const padX = 140; const padY = 40;
    const plotHeight = 200; 
    const scaleY = (plotHeight - padY) / (maxY - minY || 1);
    const scaleX = (canvas.width - padX - 40) / W;

    // 1. Draw Crust Block Polygons
    for(let li=0; li&lt;rec.levels.length; li++){
      const lvl = rec.levels[li]; ctx.beginPath();
      for(let o=0; o&lt;lvl.tops.length; o++) ctx.lineTo(padX + (lvl.tops[o].x + W/2) * scaleX, plotHeight - (lvl.tops[o].z - minY) * scaleY);
      for(let o=lvl.bottoms.length-1; o&gt;=0; o--) ctx.lineTo(padX + (lvl.bottoms[o].x + W/2) * scaleX, plotHeight - (lvl.bottoms[o].z - minY) * scaleY);
      ctx.closePath();
      ctx.fillStyle = (li===0)? &#39;rgba(40,40,40,0.18)&#39; : (li%2===0)? &#39;rgba(70,130,180,0.15)&#39; : &#39;rgba(143,188,143,0.18)&#39;;
      ctx.fill(); ctx.strokeStyle=&#39;rgba(0,0,0,0.4)&#39;; ctx.stroke();

      // 2. PLOT INTERMEDIATE LEVEL LABELS DIRECTLY ON THE GRAPH PROFILE NODES
      ctx.save(); ctx.font=&#39;7px monospace&#39;; ctx.fillStyle=&#39;#000&#39;;
      for(let o=0; o&lt;lvl.tops.length; o++){
        const cx = padX + (lvl.tops[o].x + W/2) * scaleX;
        
        if (li === 0) {
          // Top line text levels offset upwards to prevent overlapping structural elements
          const cyTop = plotHeight - (lvl.tops[o].z - minY) * scaleY;
          ctx.fillText(lvl.tops[o].z.toFixed(3), cx - 12, cyTop - 6);
        }
        
        // Dynamic bottom profile layers elevation levels placed beneath lines
        const cyBot = plotHeight - (lvl.bottoms[o].z - minY) * scaleY;
        ctx.fillText(lvl.bottoms[o].z.toFixed(3), cx - 12, cyBot + 10);
      }
      ctx.restore();
    }

    // 3. Plot Natural Ground Level (OGL) and plot elevations on graph line
    ctx.beginPath();
    for(let o=0; o&lt;rec.oglProfile.length; o++){
      const cx = padX + (rec.oglProfile[o].x + W/2) * scaleX;
      const cy = plotHeight - (rec.oglProfile[o].z - minY) * scaleY;
      if(o === 0) ctx.moveTo(cx, cy); else ctx.lineTo(cx, cy);
      
      // Plot OGL levels inline on graph with a distinct red style layout
      ctx.save(); ctx.fillStyle=&#39;#c9302c&#39;; ctx.font=&#39;7px monospace&#39;;
      ctx.fillText(rec.oglProfile[o].z.toFixed(3), cx - 12, cy - 4);
      ctx.restore();
    }
    ctx.strokeStyle = &#39;#d9534f&#39;; ctx.lineWidth = 2; ctx.setLineDash([3, 3]); ctx.stroke(); ctx.setLineDash([]);

    // 4. LOWER BOUNDING REFERENCE LEVEL SHEET DATA GRID BLOCK
    const gridStartY = 230; const rowHeight = 22;
    let gridRows = [
      { label: &quot;OFFSET DIST. (m)&quot;, data: rec.offsets.map(x =&gt; x.toFixed(2)) },
      { label: &quot;TOP CRUST LEVEL Z&quot;, data: rec.levels[0].tops.map(t =&gt; t.z.toFixed(3)) }
    ];
    for(let li=0; li&lt;rec.levels.length; li++){
      gridRows.push({ label: `BTM OF ${rec.levels[li].layerName} (m)`, data: rec.levels[li].bottoms.map(b =&gt; b.z.toFixed(3)) });
    }
    gridRows.push({ label: &quot;OGL LEVEL Z (m)&quot;, data: rec.oglProfile.map(o =&gt; o.z.toFixed(3)) });

    ctx.lineWidth = 1; ctx.strokeStyle = &#39;#444&#39;;
    gridRows.forEach((row, rIdx) =&gt; {
      const currentY = gridStartY + (rIdx * rowHeight);
      ctx.beginPath(); ctx.moveTo(15, currentY); ctx.lineTo(canvas.width - 20, currentY); ctx.stroke();
      ctx.fillStyle = &#39;#222&#39;; ctx.font = &#39;bold 9px Arial&#39;; ctx.fillText(row.label, 20, currentY + 14);

      ctx.font = &#39;9px Courier New&#39;; ctx.fillStyle = &#39;#111&#39;;
      for(let o=0; o&lt;rec.offsets.length; o++){
        const cx = padX + (rec.offsets[o].x + W/2) * scaleX;
        ctx.fillText(row.data[o], cx - 14, currentY + 14);
      }
    });
    ctx.beginPath(); ctx.moveTo(15, gridStartY + (gridRows.length * rowHeight)); ctx.lineTo(canvas.width - 20, gridStartY + (gridRows.length * rowHeight)); ctx.stroke();

    // Context Guidelines Legend Info Labels Banner
    ctx.fillStyle=&#39;#d9534f&#39;; ctx.font=&#39;bold 10px Arial&#39;; ctx.fillText(&#39;-- - -- OGL Line (Red Labels)&#39;, 20, 20);
    ctx.fillStyle=&#39;#111&#39;; ctx.fillText(&#39;Crust Levels displayed above/below layer vectors&#39;, 200, 20);
  }

  function renderSummary(){
    const summaryDiv = document.getElementById(&#39;summaryContainer&#39;); if (!summaryDiv) return; summaryDiv.innerHTML = &#39;&#39;;
    const totalLength = chainages[chainages.length-1] - chainages[0];
    let html = `&lt;p&gt;&lt;strong&gt;Net Evaluation Length:&lt;/strong&gt; ${totalLength.toFixed(3)} m&lt;/p&gt;`;
    html += &#39;&lt;h4&gt;Pavement Structural Matrix Volumes&lt;/h4&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Layer Description&lt;/th&gt;&lt;th&gt;Total Vol Summary (m³)&lt;/th&gt;&lt;/tr&gt;&#39;;
    for(let li=0; li&lt;layers.length; li++) html += `&lt;tr&gt;&lt;td&gt;&lt;strong&gt;${layers[li].name}&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;${perChainResults._volumes[li].total.toFixed(3)} m³&lt;/td&gt;&lt;/tr&gt;`;
    html += &#39;&lt;/table&gt;&lt;h4&gt;Earthwork Base Subgrade Summary Quantities&lt;/h4&gt;&lt;table&gt;&#39;;
    html += `&lt;tr&gt;&lt;td style=&quot;color:#b22222; font-weight:bold;&quot;&gt;Total Cutting (Excavation) Volume&lt;/td&gt;&lt;td style=&quot;color:#b22222; font-weight:bold;&quot;&gt;${perChainResults._earthworkTotal.cut.toFixed(3)} m³&lt;/td&gt;&lt;/tr&gt;`;
    html += `&lt;tr&gt;&lt;td style=&quot;color:#006400; font-weight:bold;&quot;&gt;Total Filling (Embankment) Volume&lt;/td&gt;&lt;td style=&quot;color:#006400; font-weight:bold;&quot;&gt;${perChainResults._earthworkTotal.fill.toFixed(3)} m³&lt;/td&gt;&lt;/tr&gt;`;
    html += &#39;&lt;/table&gt;&#39;;
    summaryDiv.innerHTML = html;
  }

  window.buildLayerRows = buildLayerRows; window.parseSurvey = parseSurvey; window.calculate = calculate;
  buildLayerRows();
});
&lt;/script&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/04/road-cross-section-generator.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-6802879958856377837</guid><pubDate>Sun, 26 Apr 2026 01:31:02 +0000</pubDate><atom:updated>2026-06-23T13:31:18.296+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><category domain="http://www.blogger.com/atom/ns#">Tender</category><title>DTP checklist generator tool</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;mr&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;PWD Expert DTP Checklist Manager&lt;/title&gt;
    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js&quot;&gt;&lt;/script&gt;
    &lt;style&gt;
        :root { --primary: #1e3a8a; --accent: #2563eb; --bg: #f1f5f9; --border: #cbd5e1; }
        body { font-family: &quot;Segoe UI&quot;, Arial, sans-serif; background: var(--bg); margin: 0; padding: 20px; color: #111; }
        .container { max-width: 1000px; margin: auto; background: #fff; padding: 25px; border-radius: 8px; box-shadow: 0 5px 15px rgba(0,0,0,0.1); }
        h2 { text-align: center; color: var(--primary); border-bottom: 3px solid var(--primary); padding-bottom: 10px; }
        
        .toolbar { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; background: #e2e8f0; padding: 12px; border-radius: 6px; align-items: center; }
        button { padding: 10px 16px; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; color: white; transition: 0.2s; }
        button:disabled { background: #94a3b8; cursor: not-allowed; }
        .btn-save { background: #16a34a; }
        .btn-load { background: #0ea5e9; }
        .btn-delete { background: #dc2626; }
        .btn-pdf { background: #7c3aed; }
        select { padding: 8px; border-radius: 4px; border: 1px solid var(--border); }

        .form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px,1fr)); gap: 15px; }
        .full { grid-column: 1 / -1; }
        label { font-size: 0.85rem; font-weight: bold; display: block; margin-bottom: 4px; }
        input { width: 100%; padding: 8px; border: 1px solid var(--border); border-radius: 4px; box-sizing: border-box; }

        .section-title { background: var(--accent); color: #fff; padding: 8px; margin-top: 20px; border-radius: 4px; font-weight: bold; }
        .pol-status { margin-top: 10px; padding: 10px; border-radius: 4px; font-size: 14px; font-weight: bold; }
        .status-valid { background: #dcfce7; color: #166534; border: 1px solid #166534; }
        .status-invalid { background: #fee2e2; color: #991b1b; border: 1px solid #991b1b; }

        #pdf-content {
            position: absolute;
            left: -9999px;
            top: 0;
            width: 700px;
            padding: 40px;
            background: white;
            color: black;
            line-height: 1.5;
        }

        .pdf-table { width: 100%; border-collapse: collapse; table-layout: fixed; margin: 15px 0; }
        .pdf-table td, .pdf-table th { border: 1px solid black; padding: 8px; font-size: 13px; text-align: left; word-wrap: break-word; }
        .center { text-align: center !important; }
        .bold { font-weight: bold; }
        .sig-table { width: 100%; border: none; margin-top: 60px; }
        .sig-table td { border: none; text-align: center; vertical-align: bottom; width: 50%; }
      header {
            background-color: yellow;
            color: blue;
            padding: 20px;
            border-radius: 8px;
            margin-bottom: 30px;
            text-align: center;
        }
        h1 { margin: 0; font-size: 24px; }
        h2 { color: #2b6cb0; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; margin-top: 30px; }
        h3 { color: #4a5568; }
        code {
            background-color: #edf2f7;
            padding: 2px 6px;
            border-radius: 4px;
            font-family: monospace;
            font-size: 0.9em;
        }
        .info-box {
            background-color: #ebf8ff;
            border-left: 4px solid #3182ce;
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 8px 8px 0;
        }
        .warning-box {
            background-color: #fffaf0;
            border-left: 4px solid #dd6b20;
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 8px 8px 0;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
            background: white;
        }
        th, td {
            border: 1px solid #cbd5e0;
            padding: 12px;
            text-align: left;
        }
        th { background-color: #f7fafc; color: #4a5568; }
        ul, ol { padding-left: 20px; }
        li { margin-bottom: 8px; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;container&quot;&gt;
    &lt;h2&gt;प्रारुप निविदा प्रपत्र (DTP) तपासणी सुची&lt;/h2&gt;
    
    &lt;div class=&quot;toolbar&quot;&gt;
        &lt;select id=&quot;projectList&quot;&gt;&lt;option value=&quot;&quot;&gt;प्रकल्प निवडा&lt;/option&gt;&lt;/select&gt;
        &lt;button onclick=&quot;loadSelected()&quot; class=&quot;btn-load&quot;&gt;लोड करा&lt;/button&gt;
        &lt;button onclick=&quot;saveProject()&quot; class=&quot;btn-save&quot;&gt;सेव्ह करा&lt;/button&gt;
        &lt;button onclick=&quot;deleteProject()&quot; class=&quot;btn-delete&quot;&gt;डिलीट&lt;/button&gt;
        &lt;button onclick=&quot;generatePDF()&quot; id=&quot;downloadBtn&quot; class=&quot;btn-pdf&quot;&gt;PDF जनरेट करा&lt;/button&gt;
    &lt;/div&gt;
  
  &lt;div class=&quot;toolbar&quot;&gt;
    &lt;button onclick=&quot;exportToJSON()&quot; style=&quot;background: #475569;&quot;&gt;Export (JSON)&lt;/button&gt;
    &lt;button onclick=&quot;importFromJSON()&quot; style=&quot;background: #64748b;&quot;&gt;Import (JSON)&lt;/button&gt;
&lt;/div&gt;

    &lt;form id=&quot;dtpForm&quot;&gt;
        &lt;div class=&quot;form-grid&quot;&gt;
            &lt;div class=&quot;full&quot;&gt;&lt;label&gt;कामाचे नांव&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;workName&quot;&gt;&lt;/div&gt;
            &lt;div class=&quot;full&quot;&gt;&lt;label&gt;संदर्भ&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;refText&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;प्रादेशिक विभाग&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;region&quot; value=&quot;नाशिक&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;जावक क्र.&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;tsNo&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;दरसुची वर्ष&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;dsYear&quot; placeholder=&quot;2025-26&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;

        &lt;div class=&quot;section-title&quot;&gt;आर्थिक तपशील (Financial Details)&lt;/div&gt;
        &lt;div class=&quot;form-grid&quot; style=&quot;margin-top:10px;&quot;&gt;
            &lt;div&gt;&lt;label&gt;Civil Work (I)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;valCivil&quot; value=&quot;0&quot; oninput=&quot;calcTotals()&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;Electrical (II)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;valElec&quot; value=&quot;0&quot; oninput=&quot;calcTotals()&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;रॉयल्टी शुल्क&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;valRoy&quot; value=&quot;0&quot; oninput=&quot;calcTotals()&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;प्रयोगशाळा शुल्क&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;valLab&quot; value=&quot;0&quot; oninput=&quot;calcTotals()&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;

        &lt;div class=&quot;section-title&quot;&gt;P.O.L. Component (%)&lt;/div&gt;
        &lt;div class=&quot;form-grid&quot; style=&quot;margin-top:10px;&quot;&gt;
            &lt;div&gt;&lt;label&gt;Labour (%)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;polLab&quot; value=&quot;0&quot; oninput=&quot;validatePOL()&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;Material (%)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;polMat&quot; value=&quot;0&quot; oninput=&quot;validatePOL()&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;P.O.L (%)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;polFuel&quot; value=&quot;0&quot; oninput=&quot;validatePOL()&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;
        &lt;div id=&quot;polMessage&quot; class=&quot;pol-status status-invalid&quot;&gt;
            P.O.L. एकूण: &lt;span id=&quot;currentTotal&quot;&gt;0&lt;/span&gt;% | &lt;span id=&quot;statusText&quot;&gt;त्रुटी: एकूण १००% आवश्यक!&lt;/span&gt;
        &lt;/div&gt;

        &lt;div class=&quot;section-title&quot;&gt;बांधकाम साहित्य दर (Basic Rates)&lt;/div&gt;
        &lt;div class=&quot;form-grid&quot; style=&quot;margin-top:10px;&quot;&gt;
            &lt;div&gt;&lt;label&gt;सिमेंट (MT)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;r_cement&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;TMT Steel (MT)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;r_tmt&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;Structural Steel (MT)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;r_struct&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;डांबर 60/70 (MT)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;r_bit60&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;डांबर 80/100 (MT)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;r_bit80&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;
      
        &lt;div class=&quot;section-title&quot;&gt;बाबींच्या परिमाणाचा तपशिल (३०% तपासणी)&lt;/div&gt;
        &lt;div style=&quot;overflow-x: auto; margin-top:10px;&quot;&gt;
            &lt;table id=&quot;boqTable&quot; style=&quot;width: 100%; border-collapse: collapse;&quot;&gt;
                &lt;thead&gt;
                    &lt;tr style=&quot;background:#f2f2f2;&quot;&gt;
                        &lt;th&gt;बाबींची यादी&lt;/th&gt;
                        &lt;th&gt;एकूण परिमाण&lt;/th&gt;
                        &lt;th&gt;युनिट&lt;/th&gt;
                        &lt;th&gt;३०% परिमाण&lt;/th&gt;
                        &lt;th&gt;बाबींची किंमत (रु.)&lt;/th&gt;
                        &lt;th&gt;काढा&lt;/th&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                    &lt;/tbody&gt;
            &lt;/table&gt;
            &lt;button type=&quot;button&quot; onclick=&quot;addRow()&quot; style=&quot;margin-top:10px; padding: 5px; color: black; background: #ddd; border-radius: 4px;&quot;&gt;+ अजून ओळ जोडा&lt;/button&gt;
        &lt;/div&gt;
    &lt;/form&gt;
&lt;/div&gt;

&lt;div id=&quot;pdf-content&quot;&gt;
    &lt;h3 class=&quot;center&quot; style=&quot;text-decoration: underline;&quot;&gt;प्रारुप निविदा प्रपत्र तपासणी सुची&lt;/h3&gt;
    &lt;div style=&quot;margin-top: 20px;&quot;&gt;
        &lt;p&gt;&lt;strong&gt;कामाचे नांव:&lt;/strong&gt; &lt;span id=&quot;p_workName&quot;&gt;&lt;/span&gt;&lt;/p&gt;
        &lt;p&gt;&lt;strong&gt;संदर्भ:&lt;/strong&gt; &lt;span id=&quot;p_refText&quot;&gt;&lt;/span&gt;&lt;/p&gt;
    &lt;/div&gt;
    &lt;p&gt;महोदय, सदर कामास मुख्य अभियंता, सा. बां. प्रादेशिक विभाग, &lt;span id=&quot;p_region&quot;&gt;&lt;/span&gt; यांनी त्यांचेकडील पत्र जा.क्र. &lt;span id=&quot;p_tsNo&quot;&gt;&lt;/span&gt; नुसार तांत्रिक मान्यता दिलेली आहे. सदर कामाचे अंदाजपत्रक हे सन &lt;span id=&quot;p_dsYear&quot;&gt;&lt;/span&gt; चे दरसुचीवर आधारीत आहे.&lt;/p&gt;

    &lt;table class=&quot;pdf-table&quot;&gt;
        &lt;tr class=&quot;bold&quot;&gt;&lt;td&gt;अ)&lt;/td&gt;&lt;td&gt;प्रारुप निविदा किंमत (Civil + Electrical)&lt;/td&gt;&lt;td id=&quot;p_tenderTotal&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;ब)&lt;/td&gt;&lt;td&gt;रॉयल्टी + प्रयोगशाळा शुल्क&lt;/td&gt;&lt;td id=&quot;p_royLabTotal&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr class=&quot;bold&quot;&gt;&lt;td&gt;क)&lt;/td&gt;&lt;td&gt;मंजुर अंदाजपत्रकाप्रमाणे एकूण किंमत&lt;/td&gt;&lt;td id=&quot;p_grandTotal&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;p&gt;&lt;strong&gt;ड) P.O.L. Component:&lt;/strong&gt;&lt;/p&gt;
    &lt;table class=&quot;pdf-table&quot; style=&quot;width: 50%;&quot;&gt;
        &lt;tr&gt;&lt;td&gt;Labour&lt;/td&gt;&lt;td id=&quot;p_polLab&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Material&lt;/td&gt;&lt;td id=&quot;p_polMat&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;P.O.L&lt;/td&gt;&lt;td id=&quot;p_polFuel&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;p&gt;&lt;strong&gt;ई) बांधकाम साहित्याचे दर:&lt;/strong&gt;&lt;/p&gt;
    &lt;table class=&quot;pdf-table&quot;&gt;
        &lt;thead&gt;&lt;tr&gt;&lt;th&gt;अ.क्र.&lt;/th&gt;&lt;th&gt;साहित्याचा तपशील&lt;/th&gt;&lt;th&gt;दर (प्रति मे. टन)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;सिमेंट (Cement)&lt;/td&gt;&lt;td id=&quot;p_r_cement&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;TMT Steel&lt;/td&gt;&lt;td id=&quot;p_r_tmt&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;Structural Steel&lt;/td&gt;&lt;td id=&quot;p_r_struct&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;डांबर 60/70&lt;/td&gt;&lt;td id=&quot;p_r_bit60&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;डांबर 80/100&lt;/td&gt;&lt;td id=&quot;p_r_bit80&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
  
    &lt;p&gt;&lt;strong&gt;बाबींच्या परिमाणाचा तपशिल (३०% तपासणी):&lt;/strong&gt;&lt;/p&gt;
    &lt;table class=&quot;pdf-table&quot;&gt;
        &lt;thead&gt;&lt;tr&gt;&lt;th&gt;अ.क्र.&lt;/th&gt;&lt;th&gt;बाबींची यादी&lt;/th&gt;&lt;th&gt;एकूण परिमाण&lt;/th&gt;&lt;th&gt;युनिट&lt;/th&gt;&lt;th&gt;३०%&lt;/th&gt;&lt;th&gt;किंमत (रु.)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
        &lt;tbody id=&quot;p_boq_rows&quot;&gt;&lt;/tbody&gt;
    &lt;/table&gt;
    &lt;table class=&quot;sig-table&quot;&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;br&gt;&lt;br&gt;____________________&lt;br&gt;&lt;strong&gt;शाखा अभियंता&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;&lt;br&gt;&lt;br&gt;____________________&lt;br&gt;&lt;strong&gt;उप विभागीय अभियंता&lt;/strong&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
&lt;/div&gt;
  
  &lt;header&gt;
    &lt;h1&gt;User Guide: PWD Checklist &amp; Draft Tender Paper (DTP) Tool&lt;/h1&gt;
    &lt;p&gt;A manual for project estimating, structural validation, and database management&lt;/p&gt;
&lt;/header&gt;

&lt;section&gt;
    &lt;h2&gt;1. Introduction&lt;/h2&gt;
    &lt;p&gt;This tool is designed to streamline the compilation, validation, and generation of &lt;strong&gt;PWD (Public Works Department) Checklists&lt;/strong&gt; and &lt;strong&gt;Draft Tender Premium (DTP)&lt;/strong&gt; documentation. Powered by a local background database, it allows you to handle project financial summaries, track fundamental construction material rates, and automate Bill of Quantities (BOQ) math efficiently.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;2. Key Features&lt;/h2&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;Local Offline Storage:&lt;/strong&gt; Uses your browser&#39;s built-in &lt;code&gt;IndexedDB&lt;/code&gt; layout named &lt;code&gt;PWD_Checklist_DB&lt;/code&gt; to save or update progress instantly without an active internet connection.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Automated Math Constraints:&lt;/strong&gt; Real-time confirmation that your labor, material, and fuel variables add up perfectly to 100%.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Smart BOQ Processor:&lt;/strong&gt; Automatic execution of specific subset parameters (e.g., automated calculation of 30% metric allowances based on item quantities).&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Dynamic Document Exporter:&lt;/strong&gt; Compiles user field variables directly into formatted PDF formats using client-side canvas generation engines.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Data Portability:&lt;/strong&gt; Native backup routines allowing seamless migration or archival via standard JSON uploads/downloads.&lt;/li&gt;
    &lt;/ul&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;3. Operating Instructions&lt;/h2&gt;

    &lt;h3&gt;Step 1: Selecting or Creating a Project&lt;/h3&gt;
    &lt;p&gt;When the application boots, it queries your browser database storage layer.&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;To start fresh:&lt;/strong&gt; Simply enter details in the clear text fields provided. By default, the app structures a baseline table row to let you input details immediately.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;To load an existing file:&lt;/strong&gt; Utilize the project dropdown selection engine at the top of the interface. Choosing an option will trigger &lt;code&gt;loadSelected()&lt;/code&gt; and populate all saved metadata elements dynamically.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3&gt;Step 2: Completing Metadata and Financial Data Blocks&lt;/h3&gt;
    &lt;p&gt;Fill out the descriptive metrics sections (Work Name, Reference String, Regional Zone, Technical Sanction Number, Schedule of Rates Year). Below that, enter your monetary valuations:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;Civil Structural Valuations&lt;/li&gt;
        &lt;li&gt;Electrical Infrastructure Allocations&lt;/li&gt;
        &lt;li&gt;Royalty Rates &amp; Labor Surcharges&lt;/li&gt;
        &lt;li&gt;Basic Material Ledger Values (Cement, TMT Steel, Structural Steel, Bitumen VG-60 / VG-80 grades)&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3&gt;Step 3: POL Allocation Validation (Crucial Check)&lt;/h3&gt;
    &lt;p&gt;The system evaluates the statutory distribution of Petroleum, Oil, and Lubricants (POL) parameters. You must input:&lt;/p&gt;
    &lt;ol&gt;
        &lt;li&gt;Labor Component Percentage (&lt;code&gt;polLab&lt;/code&gt;)&lt;/li&gt;
        &lt;li&gt;Material Component Percentage (&lt;code&gt;polMat&lt;/code&gt;)&lt;/li&gt;
        &lt;li&gt;Fuel Component Percentage (&lt;code&gt;polFuel&lt;/code&gt;)&lt;/li&gt;
    &lt;/ol&gt;
    &lt;div class=&quot;warning-box&quot;&gt;
        &lt;strong&gt;Validation Notice:&lt;/strong&gt; The engine automatically tracks these inputs. If the cumulative sum is exactly &lt;strong&gt;100%&lt;/strong&gt;, you will see a green confirmation indicator: &lt;code&gt;योग्य: एकूण १००% आहे.&lt;/code&gt;. If it deviates from 100%, a red error notice appears: &lt;code&gt;त्रुटी: एकूण १००% आवश्यक!&lt;/code&gt;, and your PDF download button will be disabled.
    &lt;/div&gt;

    &lt;h3&gt;Step 4: Managing the Bill of Quantities (BOQ) Table&lt;/h3&gt;
    &lt;p&gt;The core itemizer performs calculations instantly on user entry:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;Type your Item Name, Target Quantity, Unit metrics, and individual base Rate.&lt;/li&gt;
        &lt;li&gt;As you type a quantity value, the system automatically runs the &lt;code&gt;update30()&lt;/code&gt; routine, calculating exactly &lt;strong&gt;30%&lt;/strong&gt; of that value and rendering it under the custom tracking column.&lt;/li&gt;
        &lt;li&gt;Click the red cross icon (&lt;strong&gt;✖&lt;/strong&gt;) at the end of any given row to drop that specific index entry instantly.&lt;/li&gt;
    &lt;/ul&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;4. Control Actions Reference&lt;/h2&gt;
    &lt;table&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th&gt;Action Button / Mechanism&lt;/th&gt;
                &lt;th&gt;Underlying Operation&lt;/th&gt;
                &lt;th&gt;Outcome / Results&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Save Project&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;saveProject()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Pushes all metadata and structural array objects into IndexedDB storage and triggers a success prompt (&lt;code&gt;माहिती जतन केली!&lt;/code&gt;).&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Download PDF&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;generatePDF()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Temporarily maps all active elements to a hidden snapshot canvas, structures a clean layout page format, and initiates a localized prompt file download named &lt;code&gt;DTP_Checklist.pdf&lt;/code&gt;.&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Delete Project&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;deleteProject()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Displays a confirmation message (&lt;code&gt;काय आपण हे रेकॉर्ड डिलीट करू इच्छिता?&lt;/code&gt;). If confirmed, it purges the file from the database and resets the input screen.&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Export Backup&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;exportToJSON()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Pulls the entire database and compiles a downloadable backup document appended with the current date string (e.g., &lt;code&gt;.json&lt;/code&gt;).&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Import Data&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;importFromJSON()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Opens a local file dialog window to read JSON files, generates new safe ID indicators for each record, updates your local store, and updates the view list.&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;5. Technical Notes &amp; Best Practices&lt;/h2&gt;
    &lt;div class=&quot;info-box&quot;&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;Browser Storage Dependence:&lt;/strong&gt; Clearing your web browser cache or cookies completely might flush your active data if storage properties are unpinned. It is highly recommended to perform an &lt;strong&gt;Export Backup&lt;/strong&gt; routinely to safeguard records.&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;External Libraries Required:&lt;/strong&gt; The file export engine depends heavily on having access to external runtime helper libraries, specifically &lt;code&gt;html2canvas&lt;/code&gt; and &lt;code&gt;jsPDF&lt;/code&gt;, loaded on the hosting window envelope.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;
&lt;/section&gt;

&lt;script&gt;
    let db;
    let currentId = null;

    const request = indexedDB.open(&quot;PWD_Checklist_DB&quot;, 1);
    request.onupgradeneeded = e =&gt; {
        db = e.target.result;
        db.createObjectStore(&quot;projects&quot;, { keyPath: &quot;id&quot;, autoIncrement: true });
    };
    request.onsuccess = e =&gt; { db = e.target.result; refreshList(); addRow(); };

    function validatePOL() {
        const l = parseFloat(document.getElementById(&#39;polLab&#39;).value) || 0;
        const m = parseFloat(document.getElementById(&#39;polMat&#39;).value) || 0;
        const p = parseFloat(document.getElementById(&#39;polFuel&#39;).value) || 0;
        const total = Math.round((l + m + p) * 100) / 100;
        
        document.getElementById(&#39;currentTotal&#39;).innerHTML = total;
        const msgBox = document.getElementById(&#39;polMessage&#39;);
        const statusText = document.getElementById(&#39;statusText&#39;);
        const btn = document.getElementById(&#39;downloadBtn&#39;);

        if (total === 100) {
            msgBox.className = &quot;pol-status status-valid&quot;;
            statusText.innerHTML = &quot;योग्य: एकूण १००% आहे.&quot;;
            btn.disabled = false;
        } else {
            msgBox.className = &quot;pol-status status-invalid&quot;;
            statusText.innerHTML = &quot;त्रुटी: एकूण १००% आवश्यक!&quot;;
            btn.disabled = true;
        }
    }

    function saveProject() {
        const boqData = [];
        document.querySelectorAll(&quot;#boqTable tbody tr&quot;).forEach(row =&gt; {
            const item = row.cells[0]?.querySelector(&quot;input&quot;)?.value || &quot;&quot;;
            const qty = parseFloat(row.cells[1]?.querySelector(&quot;input&quot;)?.value) || 0;
            const unit = row.cells[2]?.querySelector(&quot;input&quot;)?.value || &quot;&quot;;
            const rate = parseFloat(row.cells[4]?.querySelector(&quot;input&quot;)?.value) || 0;
            if (item.trim() !== &quot;&quot;) boqData.push({ item, qty, unit, rate });
        });

        const data = {
            workName: document.getElementById(&#39;workName&#39;).value,
            refText: document.getElementById(&#39;refText&#39;).value,
            region: document.getElementById(&#39;region&#39;).value,
            tsNo: document.getElementById(&#39;tsNo&#39;).value,
            dsYear: document.getElementById(&#39;dsYear&#39;).value,
            valCivil: document.getElementById(&#39;valCivil&#39;).value,
            valElec: document.getElementById(&#39;valElec&#39;).value,
            valRoy: document.getElementById(&#39;valRoy&#39;).value,
            valLab: document.getElementById(&#39;valLab&#39;).value,
            polLab: document.getElementById(&#39;polLab&#39;).value,
            polMat: document.getElementById(&#39;polMat&#39;).value,
            polFuel: document.getElementById(&#39;polFuel&#39;).value,
            r_cement: document.getElementById(&#39;r_cement&#39;).value,
            r_tmt: document.getElementById(&#39;r_tmt&#39;).value,
            r_struct: document.getElementById(&#39;r_struct&#39;).value,
            r_bit60: document.getElementById(&#39;r_bit60&#39;).value,
            r_bit80: document.getElementById(&#39;r_bit80&#39;).value,
            boq: boqData
        };

        const tx = db.transaction(&quot;projects&quot;, &quot;readwrite&quot;);
        const store = tx.objectStore(&quot;projects&quot;);
        if (currentId) data.id = currentId;
        
        const saveRequest = currentId ? store.put(data) : store.add(data);
        saveRequest.onsuccess = () =&gt; { alert(&quot;माहिती जतन केली!&quot;); refreshList(); };
    }

    function refreshList() {
        const list = document.getElementById(&#39;projectList&#39;);
        list.innerHTML = &#39;&lt;option value=&quot;&quot;&gt;निवडा...&lt;/option&gt;&#39;;
        db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).getAll().onsuccess = e =&gt; {
            e.target.result.forEach(p =&gt; {
                let opt = document.createElement(&quot;option&quot;);
                opt.value = p.id;
                opt.text = p.workName.substring(0, 40) + &quot;...&quot;;
                list.add(opt);
            });
        };
    }

    function loadSelected() {
        const id = parseInt(document.getElementById(&#39;projectList&#39;).value);
        if (!id) return;
        currentId = id;
        db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(id).onsuccess = e =&gt; {
            const d = e.target.result;
            Object.keys(d).forEach(key =&gt; {
                if(document.getElementById(key)) document.getElementById(key).value = d[key];
            });
            validatePOL();
            const tbody = document.querySelector(&quot;#boqTable tbody&quot;);
            tbody.innerHTML = &quot;&quot;;
            if (d.boq &amp;&amp; d.boq.length &gt; 0) {
                d.boq.forEach(row =&gt; addRowWithData(row));
            } else {
                addRow();
            }
        };
    }

    function addRowWithData(row) {
        const tbody = document.querySelector(&quot;#boqTable tbody&quot;);
        const tr = document.createElement(&quot;tr&quot;);
        tr.innerHTML = `
            &lt;td&gt;&lt;input type=&quot;text&quot; value=&quot;${row.item}&quot; style=&quot;width:90%&quot;&gt;&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;number&quot; value=&quot;${row.qty}&quot; oninput=&quot;update30(this)&quot; style=&quot;width:90%&quot;&gt;&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;text&quot; value=&quot;${row.unit}&quot; style=&quot;width:80%&quot;&gt;&lt;/td&gt;
            &lt;td class=&quot;calc-30 center&quot;&gt;${(row.qty * 0.3).toFixed(2)}&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;number&quot; value=&quot;${row.rate}&quot; style=&quot;width:90%&quot;&gt;&lt;/td&gt;
            &lt;td class=&quot;center&quot;&gt;&lt;button type=&quot;button&quot; onclick=&quot;this.parentElement.parentElement.remove()&quot; style=&quot;color:red; background:none; border:none; cursor:pointer;&quot;&gt;✖&lt;/button&gt;&lt;/td&gt;
        `;
        tbody.appendChild(tr);
    }

    function addRow() {
        const tbody = document.querySelector(&quot;#boqTable tbody&quot;);
        const tr = document.createElement(&quot;tr&quot;);
        tr.innerHTML = `
            &lt;td&gt;&lt;input type=&quot;text&quot; placeholder=&quot;Item name&quot; style=&quot;width:90%&quot;&gt;&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;number&quot; oninput=&quot;update30(this)&quot; style=&quot;width:90%&quot;&gt;&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;text&quot; placeholder=&quot;Unit&quot; style=&quot;width:80%&quot;&gt;&lt;/td&gt;
            &lt;td class=&quot;calc-30 center&quot;&gt;-&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;number&quot; style=&quot;width:90%&quot;&gt;&lt;/td&gt;
            &lt;td class=&quot;center&quot;&gt;&lt;button type=&quot;button&quot; onclick=&quot;this.parentElement.parentElement.remove()&quot; style=&quot;color:red; background:none; border:none; cursor:pointer;&quot;&gt;✖&lt;/button&gt;&lt;/td&gt;
        `;
        tbody.appendChild(tr);
    }

    function update30(input) {
        const qty = parseFloat(input.value) || 0;
        input.parentElement.parentElement.querySelector(&#39;.calc-30&#39;).innerHTML = (qty * 0.3).toFixed(2);
    }

    function deleteProject() {
        const id = parseInt(document.getElementById(&#39;projectList&#39;).value);
        if(!id) return;
        if(confirm(&quot;काय आपण हे रेकॉर्ड डिलीट करू इच्छिता?&quot;)) {
            db.transaction(&quot;projects&quot;, &quot;readwrite&quot;).objectStore(&quot;projects&quot;).delete(id).onsuccess = () =&gt; {
                currentId = null;
                document.getElementById(&#39;dtpForm&#39;).reset();
                refreshList();
            };
        }
    }

    async function generatePDF() {
        const el = document.getElementById(&quot;pdf-content&quot;);
        const getV = (id) =&gt; document.getElementById(id)?.value || &quot;________&quot;;
        const fmt = (num) =&gt; parseFloat(num).toLocaleString(&#39;en-IN&#39;);

        document.getElementById(&quot;p_workName&quot;).innerHTML = getV(&quot;workName&quot;);
        document.getElementById(&quot;p_refText&quot;).innerHTML = getV(&quot;refText&quot;);
        document.getElementById(&quot;p_region&quot;).innerHTML = getV(&quot;region&quot;);
        document.getElementById(&quot;p_tsNo&quot;).innerHTML = getV(&quot;tsNo&quot;);
        document.getElementById(&quot;p_dsYear&quot;).innerHTML = getV(&quot;dsYear&quot;);

        const civil = parseFloat(getV(&quot;valCivil&quot;)) || 0;
        const elec = parseFloat(getV(&quot;valElec&quot;)) || 0;
        const roy = parseFloat(getV(&quot;valRoy&quot;)) || 0;
        const lab = parseFloat(getV(&quot;valLab&quot;)) || 0;

        document.getElementById(&quot;p_tenderTotal&quot;).innerHTML = &quot;रु. &quot; + fmt(civil + elec);
        document.getElementById(&quot;p_royLabTotal&quot;).innerHTML = &quot;रु. &quot; + fmt(roy + lab);
        document.getElementById(&quot;p_grandTotal&quot;).innerHTML = &quot;रु. &quot; + fmt(civil + elec + roy + lab);

        document.getElementById(&quot;p_polLab&quot;).innerHTML = getV(&quot;polLab&quot;) + &quot;%&quot;;
        document.getElementById(&quot;p_polMat&quot;).innerHTML = getV(&quot;polMat&quot;) + &quot;%&quot;;
        document.getElementById(&quot;p_polFuel&quot;).innerHTML = getV(&quot;polFuel&quot;) + &quot;%&quot;;
        
        [&#39;r_cement&#39;, &#39;r_tmt&#39;, &#39;r_struct&#39;, &#39;r_bit60&#39;, &#39;r_bit80&#39;].forEach(id =&gt; {
            document.getElementById(&quot;p_&quot; + id).innerHTML = fmt(getV(id));
        });

        const pdfRows = document.getElementById(&quot;p_boq_rows&quot;);
        pdfRows.innerHTML = &quot;&quot;;
        document.querySelectorAll(&quot;#boqTable tbody tr&quot;).forEach((row, idx) =&gt; {
            const item = row.cells[0].querySelector(&quot;input&quot;).value;
            if(item) {
                const tr = document.createElement(&quot;tr&quot;);
                tr.innerHTML = `&lt;td&gt;${idx+1}&lt;/td&gt;&lt;td&gt;${item}&lt;/td&gt;&lt;td&gt;${row.cells[1].querySelector(&quot;input&quot;).value}&lt;/td&gt;&lt;td&gt;${row.cells[2].querySelector(&quot;input&quot;).value}&lt;/td&gt;&lt;td&gt;${row.cells[3].innerHTML}&lt;/td&gt;&lt;td&gt;${row.cells[4].querySelector(&quot;input&quot;).value}&lt;/td&gt;`;
                pdfRows.appendChild(tr);
            }
        });

        el.style.left = &quot;0&quot;; // Temporarily bring into view for capture
        const canvas = await html2canvas(el, { scale: 2 });
        const imgData = canvas.toDataURL(&quot;image/png&quot;);
        const { jsPDF } = window.jspdf;
        const pdf = new jsPDF(&quot;p&quot;, &quot;mm&quot;, &quot;a4&quot;);
        pdf.addImage(imgData, &#39;PNG&#39;, 0, 0, 210, (canvas.height * 210) / canvas.width);
        pdf.save(`DTP_Checklist.pdf`);
        el.style.left = &quot;-9999px&quot;; // Hide again
    }

    function calcTotals() {
        console.log(&quot;Financials recalculated.&quot;);
    }
  function exportToJSON() {
    const tx = db.transaction(&quot;projects&quot;, &quot;readonly&quot;);
    const store = tx.objectStore(&quot;projects&quot;);
    const request = store.getAll();

    request.onsuccess = (e) =&gt; {
        const data = e.target.result;
        if (data.length === 0) {
            alert(&quot;निर्यात करण्यासाठी कोणतीही माहिती उपलब्ध नाही!&quot;);
            return;
        }

        const blob = new Blob([JSON.stringify(data, null, 2)], { type: &quot;application/json&quot; });
        const url = URL.createObjectURL(blob);
        const a = document.createElement(&quot;a&quot;);
        
        a.href = url;
        a.download = `DTP_Checklist_Backup_${new Date().toISOString().slice(0, 10)}.json`;
        document.body.appendChild(a);
        a.click();
        
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    };
}
  
  function importFromJSON() {
    const input = document.createElement(&quot;input&quot;);
    input.type = &quot;file&quot;;
    input.accept = &quot;.json&quot;;

    input.onchange = (event) =&gt; {
        const file = event.target.files[0];
        const reader = new FileReader();

        reader.onload = (e) =&gt; {
            try {
                const importedData = JSON.parse(e.target.result);
                const tx = db.transaction(&quot;projects&quot;, &quot;readwrite&quot;);
                const store = tx.objectStore(&quot;projects&quot;);

                importedData.forEach((project) =&gt; {
                    // Delete the old ID to let IndexedDB generate a new unique one
                    delete project.id; 
                    store.add(project);
                });

                tx.oncomplete = () =&gt; {
                    alert(&quot;माहिती यशस्वीरित्या आयात केली!&quot;);
                    refreshList();
                };
            } catch (err) {
                alert(&quot;त्रुटी: फाईल वाचता आली नाही. कृपया योग्य JSON फाईल निवडा.&quot;);
                console.error(err);
            }
        };
        reader.readAsText(file);
    };

    input.click();
}
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/04/dtp-checklist.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-1890939739961428550</guid><pubDate>Sat, 25 Apr 2026 10:51:46 +0000</pubDate><atom:updated>2026-06-23T14:06:17.428+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Drawings</category><category domain="http://www.blogger.com/atom/ns#">Software</category><title>Flowchart generating tool</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;Visual Flowchart Architect Pro&lt;/title&gt;

&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdn.tailwindcss.com&quot;&gt;&lt;/script&gt;

&lt;style&gt;
.node-input-group { border-left: 4px solid #3b82f6; padding-left: 1rem; margin-bottom: 1.5rem; }
.node-card { background: white; padding: 1rem; border-radius: 0.5rem; border: 1px solid #e5e7eb; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
.preview-img { width: 40px; height: 40px; object-fit: cover; border-radius: 4px; border: 1px solid #ddd; }
&lt;/style&gt;
&lt;/head&gt;

&lt;body class=&quot;bg-gray-50 p-4&quot;&gt;

&lt;div class=&quot;max-w-7xl mx-auto&quot;&gt;

&lt;header class=&quot;bg-white p-4 rounded-xl shadow-sm border mb-6 flex flex-wrap gap-4 items-end justify-between&quot;&gt;
&lt;div class=&quot;flex flex-wrap gap-4 items-end&quot;&gt;

&lt;div&gt;
&lt;label class=&quot;block text-xs font-bold text-gray-500 mb-1&quot;&gt;Chart Name&lt;/label&gt;
&lt;input type=&quot;text&quot; id=&quot;chart-name&quot; class=&quot;border rounded p-2 text-sm w-48&quot;&gt;
&lt;/div&gt;

&lt;div&gt;
&lt;label class=&quot;block text-xs font-bold text-gray-500 mb-1&quot;&gt;Layout Orientation&lt;/label&gt;
&lt;select id=&quot;chart-layout&quot; onchange=&quot;generateChart()&quot; class=&quot;border rounded p-2 text-sm w-36 bg-white font-medium&quot;&gt;
&lt;option value=&quot;TD&quot;&gt;Top to Down (TD)&lt;/option&gt;
&lt;option value=&quot;LR&quot;&gt;Left to Right (LR)&lt;/option&gt;
&lt;/select&gt;
&lt;/div&gt;

&lt;div&gt;
&lt;label class=&quot;block text-xs font-bold text-gray-500 mb-1&quot;&gt;Saved History&lt;/label&gt;
&lt;select id=&quot;saved-charts-dropdown&quot; class=&quot;border rounded p-2 text-sm w-40 bg-white&quot;&gt;
&lt;option value=&quot;&quot;&gt;-- Load --&lt;/option&gt;
&lt;/select&gt;
&lt;/div&gt;

&lt;div class=&quot;flex gap-1&quot;&gt;
&lt;button onclick=&quot;loadChart()&quot; class=&quot;bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-2 rounded text-sm font-semibold&quot;&gt;Load&lt;/button&gt;
&lt;button onclick=&quot;deleteChart()&quot; class=&quot;bg-red-500 hover:bg-red-600 text-white px-3 py-2 rounded text-sm font-semibold&quot;&gt;Delete&lt;/button&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div class=&quot;flex gap-2&quot;&gt;
&lt;button onclick=&quot;generateChart()&quot; class=&quot;bg-blue-600 hover:bg-blue-700 text-white px-5 py-2 rounded font-bold&quot;&gt;Preview&lt;/button&gt;
&lt;button onclick=&quot;saveToDB()&quot; class=&quot;bg-purple-600 hover:bg-purple-700 text-white px-5 py-2 rounded font-bold&quot;&gt;Save&lt;/button&gt;
&lt;button onclick=&quot;exportSVG()&quot; class=&quot;bg-green-600 hover:bg-green-700 text-white px-5 py-2 rounded font-bold&quot;&gt;Export&lt;/button&gt;
&lt;/div&gt;
&lt;/header&gt;

&lt;div class=&quot;grid grid-cols-1 lg:grid-cols-2 gap-8&quot;&gt;

&lt;div id=&quot;builder-container&quot;&gt;

&lt;div class=&quot;node-input-group&quot; data-node-id=&quot;1&quot; data-level=&quot;1&quot;&gt;
&lt;div class=&quot;node-card bg-blue-50 border-blue-200 relative&quot;&gt;
&lt;textarea class=&quot;node-text w-full p-2 border rounded mb-2 text-sm&quot; rows=&quot;2&quot;&gt;Start&lt;/textarea&gt;
&lt;input type=&quot;file&quot; onchange=&quot;handleImgPreview(this)&quot; class=&quot;text-xs w-full&quot;&gt;
&lt;input type=&quot;hidden&quot; class=&quot;node-image-data&quot;&gt;
&lt;div class=&quot;img-preview-container mt-2&quot;&gt;&lt;/div&gt;
&lt;button onclick=&quot;addChild(&#39;1&#39;)&quot; class=&quot;text-blue-600 text-xs mt-2 font-semibold&quot;&gt;+ Add Child&lt;/button&gt;
&lt;/div&gt;
&lt;div class=&quot;children-container ml-6&quot;&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div class=&quot;bg-white p-6 rounded-xl shadow-md border&quot;&gt;
&lt;div id=&quot;mermaid-render&quot; class=&quot;overflow-auto&quot;&gt;Preview here&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;

    &lt;nav class=&quot;sticky top-0 bg-white/80 backdrop-blur-md border-b border-slate-200 z-50&quot;&gt;
        &lt;div class=&quot;max-w-5xl mx-auto px-4 h-16 flex items-center justify-between&quot;&gt;
            &lt;div class=&quot;flex items-center gap-2 font-bold text-indigo-600 text-lg&quot;&gt;
                &lt;svg class=&quot;w-6 height-6&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h2a2 2 0 00-2 2&quot;&gt;&lt;/path&gt;&lt;/svg&gt;
                Flowchart generator
            &lt;/div&gt;
            &lt;a href=&quot;#quick-start&quot; class=&quot;bg-indigo-600 hover:bg-indigo-700 text-white text-sm font-semibold px-4 py-2 rounded-lg shadow-sm transition&quot;&gt;Quick Start&lt;/a&gt;
        &lt;/div&gt;
    &lt;/nav&gt;

    &lt;div class=&quot;max-w-5xl mx-auto px-4 py-10 grid grid-cols-1 md:grid-cols-4 gap-8&quot;&gt;
        
        &lt;aside class=&quot;md:col-span-1 space-y-2 hidden md:block&quot;&gt;
            &lt;div class=&quot;sticky top-24 space-y-1 text-sm font-medium text-slate-500&quot;&gt;
                &lt;span class=&quot;block text-xs font-bold uppercase tracking-wider text-slate-400 mb-2 px-2&quot;&gt;Documentation&lt;/span&gt;
                &lt;a href=&quot;#overview&quot; class=&quot;block px-3 py-2 text-indigo-600 bg-indigo-50 rounded-lg font-semibold&quot;&gt;1. Overview&lt;/a&gt;
                &lt;a href=&quot;#node-management&quot; class=&quot;block px-3 py-2 hover:text-slate-900 hover:bg-slate-100 rounded-lg&quot;&gt;2. Managing Nodes&lt;/a&gt;
                &lt;a href=&quot;#multiline-text&quot; class=&quot;block px-3 py-2 hover:text-slate-900 hover:bg-slate-100 rounded-lg&quot;&gt;3. Multiline Text &amp; Formatting&lt;/a&gt;
                &lt;a href=&quot;#layout-customization&quot; class=&quot;block px-3 py-2 hover:text-slate-900 hover:bg-slate-100 rounded-lg&quot;&gt;4. Layout &amp; Orientation&lt;/a&gt;
                &lt;a href=&quot;#database-history&quot; class=&quot;block px-3 py-2 hover:text-slate-900 hover:bg-slate-100 rounded-lg&quot;&gt;5. Saving &amp; Local History&lt;/a&gt;
                &lt;a href=&quot;#exporting&quot; class=&quot;block px-3 py-2 hover:text-slate-900 hover:bg-slate-100 rounded-lg&quot;&gt;6. Exporting Files&lt;/a&gt;
            &lt;/div&gt;
        &lt;/aside&gt;

        &lt;main class=&quot;md:col-span-3 space-y-12 bg-white p-6 md:p-10 rounded-2xl border border-slate-200 shadow-sm&quot;&gt;
            
            &lt;section id=&quot;overview&quot; class=&quot;scroll-mt-20&quot;&gt;
                &lt;h1 class=&quot;text-3xl font-extrabold text-slate-900 tracking-tight mb-2&quot;&gt;Flowchart generator&lt;/h1&gt;
                &lt;p class=&quot;text-slate-600 leading-relaxed mb-6&quot;&gt;
                    This interactive application allows you to map complex, deeply nested relational tree flows using dynamic, auto-colored nodes. Built on a low-overhead, browser-native pipeline, it processes live changes directly on your machine without external cloud dependencies.
                &lt;/p&gt;
                &lt;div class=&quot;bg-amber-50 border-l-4 border-amber-500 p-4 rounded-r-lg&quot;&gt;
                    &lt;div class=&quot;flex&quot;&gt;
                        &lt;div class=&quot;flex-shrink-0&quot;&gt;
                            &lt;svg class=&quot;h-5 w-5 text-amber-500&quot; fill=&quot;currentColor&quot; viewBox=&quot;0 0 20 20&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z&quot; clip-rule=&quot;evenodd&quot;/&gt;&lt;/svg&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;ml-3&quot;&gt;
                            &lt;p class=&quot;text-sm text-amber-800 font-medium&quot;&gt;Local-First Storage Notice&lt;/p&gt;
                            &lt;p class=&quot;text-xs text-amber-700 mt-1&quot;&gt;All diagram database operations happen locally via IndexedDB. Clearing your browser cookies or storage history could permanently erase saved local drafts unless they are exported as SVG graphics.&lt;/p&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/section&gt;

            &lt;hr class=&quot;border-slate-200&quot;&gt;

            &lt;section id=&quot;node-management&quot; class=&quot;scroll-mt-20&quot;&gt;
                &lt;h2 class=&quot;text-2xl font-bold text-slate-900 mb-4&quot;&gt;2. Managing Nodes and Steps&lt;/h2&gt;
                &lt;p class=&quot;text-slate-600 mb-4&quot;&gt;The flowchart is organized hierarchically starting from a single, permanent primary starting element.&lt;/p&gt;
                &lt;ul class=&quot;space-y-3 pl-5 list-disc text-slate-600&quot;&gt;
                    &lt;li&gt;&lt;strong class=&quot;text-slate-800&quot;&gt;Adding Pathways:&lt;/strong&gt; Click the blue &lt;span class=&quot;text-blue-600 font-semibold&quot;&gt;+ Add Child&lt;/span&gt; link inside any card to create a sub-step connected to that specific card.&lt;/li&gt;
                    &lt;li&gt;&lt;strong class=&quot;text-slate-800&quot;&gt;Customizing Branch Conditions:&lt;/strong&gt; Every sub-step generates a small path-link input field above it (defaults to &lt;em&gt;&quot;leads to&quot;&lt;/em&gt;). Type inside this box to change the text rendered directly over the connector lines.&lt;/li&gt;
                    &lt;li&gt;&lt;strong class=&quot;text-slate-800&quot;&gt;Pruning Branches:&lt;/strong&gt; Click the small red cross (&lt;span class=&quot;text-red-500 font-semibold&quot;&gt;×&lt;/span&gt;) at the top right of a component card to remove that element. &lt;span class=&quot;text-red-600 font-medium&quot;&gt;Warning:&lt;/span&gt; Removing a node instantly deletes all subordinate child nodes connected below it.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/section&gt;

            &lt;hr class=&quot;border-slate-200&quot;&gt;

            &lt;section id=&quot;multiline-text&quot; class=&quot;scroll-mt-20&quot;&gt;
                &lt;h2 class=&quot;text-2xl font-bold text-slate-900 mb-4&quot;&gt;3. Multiline Text &amp; Formatting&lt;/h2&gt;
                &lt;p class=&quot;text-slate-600 mb-4&quot;&gt;To support highly detailed procedures (such as physical layout checklists or engineering summaries), the text module handles explicit structure formatting:&lt;/p&gt;
                
                &lt;div class=&quot;grid grid-cols-1 sm:grid-cols-2 gap-4 my-4&quot;&gt;
                    &lt;div class=&quot;border border-slate-200 p-4 rounded-xl bg-slate-50&quot;&gt;
                        &lt;span class=&quot;block text-xs font-bold text-slate-400 mb-2 uppercase&quot;&gt;Input Behavior&lt;/span&gt;
                        &lt;p class=&quot;text-sm text-slate-600&quot;&gt;Pressing &lt;kbd class=&quot;px-1.5 py-0.5 bg-white border rounded text-xs shadow-sm font-mono&quot;&gt;Enter&lt;/kbd&gt; inside a card&#39;s textarea splits lines manually, expanding the editor window naturally.&lt;/p&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;border border-slate-200 p-4 rounded-xl bg-slate-50&quot;&gt;
                        &lt;span class=&quot;block text-xs font-bold text-slate-400 mb-2 uppercase&quot;&gt;Rendering Engine Boundary&lt;/span&gt;
                        &lt;p class=&quot;text-sm text-slate-600&quot;&gt;Shapes are limited to a clear maximum width profile of &lt;code class=&quot;font-mono text-indigo-600&quot;&gt;220px&lt;/code&gt;. Long continuous paragraphs automatically wrap gracefully inside structural boxes.&lt;/p&gt;
                    &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class=&quot;bg-indigo-50 border-l-4 border-indigo-500 p-4 rounded-r-lg&quot;&gt;
                    &lt;h4 class=&quot;text-indigo-900 font-bold text-sm mb-1&quot;&gt;🎨 Automatic Node Color Identifiers&lt;/h4&gt;
                    &lt;p class=&quot;text-xs text-indigo-800 leading-relaxed&quot;&gt;
                        To maintain visual distinctiveness, every node calculation generates a completely unique pastel background tint and deep accent outline border matching its system unique identification ID. This prevents visual confusion across massive structures.
                    &lt;/p&gt;
                &lt;/div&gt;
            &lt;/section&gt;

            &lt;hr class=&quot;border-slate-200&quot;&gt;

            &lt;section id=&quot;layout-customization&quot; class=&quot;scroll-mt-20&quot;&gt;
                &lt;h2 class=&quot;text-2xl font-bold text-slate-900 mb-4&quot;&gt;4. Layout Orientation Handling&lt;/h2&gt;
                &lt;p class=&quot;text-slate-600 mb-3&quot;&gt;Depending on the structure of your data path, changing the workflow alignment can dramatically improve readability:&lt;/p&gt;
                &lt;div class=&quot;space-y-3&quot;&gt;
                    &lt;div class=&quot;flex items-start gap-3&quot;&gt;
                        &lt;span class=&quot;flex-shrink-0 mt-1 bg-slate-100 text-slate-700 text-xs font-mono font-bold px-2 py-0.5 rounded border&quot;&gt;TD&lt;/span&gt;
                        &lt;div&gt;
                            &lt;strong class=&quot;text-slate-800 text-sm block&quot;&gt;Top to Down Layout (Vertical)&lt;/strong&gt;
                            &lt;span class=&quot;text-xs text-slate-500&quot;&gt;Ideal for traditional structural workflows, nested hierarchies, or standard logic execution sequences.&lt;/span&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;flex items-start gap-3&quot;&gt;
                        &lt;span class=&quot;flex-shrink-0 mt-1 bg-slate-100 text-slate-700 text-xs font-mono font-bold px-2 py-0.5 rounded border&quot;&gt;LR&lt;/span&gt;
                        &lt;div&gt;
                            &lt;strong class=&quot;text-slate-800 text-sm block&quot;&gt;Left to Right Layout (Horizontal)&lt;/strong&gt;
                            &lt;span class=&quot;text-xs text-slate-500&quot;&gt;Perfect for long linear milestones, time-series projections, or rendering diagrams with very deep multiline paragraphs to maximize vertical room.&lt;/span&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
                &lt;p class=&quot;text-xs text-slate-500 mt-4 italic&quot;&gt;Tip: Flipping the Layout drop-down automatically re-renders the diagram preview engine instantly without requiring a full manual refresh cycle.&lt;/p&gt;
            &lt;/section&gt;

            &lt;hr class=&quot;border-slate-200&quot;&gt;

            &lt;section id=&quot;database-history&quot; class=&quot;scroll-mt-20&quot;&gt;
                &lt;h2 class=&quot;text-2xl font-bold text-slate-900 mb-4&quot;&gt;5. Saving &amp; Local History Workspace&lt;/h2&gt;
                &lt;p class=&quot;text-slate-600 mb-4&quot;&gt;Managing project file persistence operates via the top header utility options panel:&lt;/p&gt;
                &lt;ol class=&quot;space-y-3 pl-5 list-decimal text-slate-600 text-sm&quot;&gt;
                    &lt;li&gt;&lt;strong&gt;Naming Drafts:&lt;/strong&gt; Fill out the &lt;em class=&quot;font-medium text-slate-800&quot;&gt;Chart Name&lt;/em&gt; text input area before committing records.&lt;/li&gt;
                    &lt;li&gt;&lt;strong&gt;Saving Progress:&lt;/strong&gt; Clicking &lt;span class=&quot;bg-purple-100 text-purple-700 font-semibold px-1.5 py-0.5 rounded text-xs border border-purple-200&quot;&gt;Save&lt;/span&gt; serializes your structural layout map, media strings, multiline formats, and your current layout orientation configuration into local storage.&lt;/li&gt;
                    &lt;li&gt;&lt;strong&gt;Reloading Sessions:&lt;/strong&gt; To pick up where you left off, expand the &lt;em class=&quot;font-medium text-slate-800&quot;&gt;Saved History&lt;/em&gt; selection drop-down menu, click the target workspace title, and choose &lt;span class=&quot;bg-indigo-100 text-indigo-700 font-semibold px-1.5 py-0.5 rounded text-xs border border-indigo-200&quot;&gt;Load&lt;/span&gt;.&lt;/li&gt;
                &lt;/ol&gt;
            &lt;/section&gt;

            &lt;hr class=&quot;border-slate-200&quot;&gt;

            &lt;section id=&quot;exporting&quot; class=&quot;scroll-mt-20&quot;&gt;
                &lt;h2 class=&quot;text-2xl font-bold text-slate-900 mb-4&quot;&gt;6. Document Production &amp; Vector Exporting&lt;/h2&gt;
                &lt;p class=&quot;text-slate-600 mb-4&quot;&gt;Clicking the green &lt;span class=&quot;bg-green-100 text-green-700 font-semibold px-1.5 py-0.5 rounded text-xs border border-green-200&quot;&gt;Export&lt;/span&gt; action generates a full high-resolution vector graphic format suitable for design files, printouts, or project slide insertions.&lt;/p&gt;
                
                &lt;div class=&quot;bg-slate-50 border border-slate-200 rounded-xl p-4&quot;&gt;
                    &lt;span class=&quot;block text-xs font-bold text-slate-400 mb-2 uppercase&quot;&gt;Automated Filename Structure&lt;/span&gt;
                    &lt;div class=&quot;flex flex-wrap items-center gap-2 text-sm font-mono bg-white p-3 rounded-lg border shadow-inner text-slate-700&quot;&gt;
                        &lt;span class=&quot;text-indigo-600 font-semibold&quot;&gt;[Sanitized_Project_Name]&lt;/span&gt;
                        &lt;span class=&quot;text-slate-400&quot;&gt;_&lt;/span&gt;
                        &lt;span class=&quot;text-emerald-600 font-semibold&quot;&gt;[YYYY-MM-DD]&lt;/span&gt;
                        &lt;span class=&quot;text-slate-400&quot;&gt;.svg&lt;/span&gt;
                    &lt;/div&gt;
                    &lt;p class=&quot;text-xs text-slate-500 mt-2 leading-relaxed&quot;&gt;
                        The utility scrubs formatting characters out of your chart title, replaces blank spaces with underscores (&lt;code class=&quot;font-mono&quot;&gt;_&lt;/code&gt;), and appends today&#39;s calendar stamp dynamically. If no project title is specified, it gracefully falls back to &lt;code class=&quot;font-mono&quot;&gt;flowchart_[Date].svg&lt;/code&gt;.
                    &lt;/p&gt;
                &lt;/div&gt;
            &lt;/section&gt;

        &lt;/main&gt;
    &lt;/div&gt;

    &lt;footer class=&quot;bg-slate-900 text-slate-400 text-xs py-8 border-t border-slate-800 mt-20&quot;&gt;
        &lt;div class=&quot;max-w-5xl mx-auto px-4 text-center space-y-2&quot;&gt;
            &lt;p class=&quot;font-semibold text-slate-300&quot;&gt;Visual Flowchart Architect Pro • Documentation Console&lt;/p&gt;
            &lt;p&gt;Rendered locally via Scalable Vector Engine pipelines.&lt;/p&gt;
        &lt;/div&gt;
    &lt;/footer&gt;

&lt;script&gt;

/* ---------------- MERMAID ---------------- */

mermaid.initialize({
startOnLoad:false,
securityLevel:&#39;loose&#39;,
flowchart:{ htmlLabels:true }
});

/* ---------------- IMAGE ---------------- */

function handleImgPreview(input){
const container=input.parentElement.querySelector(&#39;.img-preview-container&#39;);
const hidden=input.parentElement.querySelector(&#39;.node-image-data&#39;);

if(input.files[0]){
const reader=new FileReader();
reader.onload=e=&gt;{
const img=new Image();
img.onload=function(){
const canvas=document.createElement(&#39;canvas&#39;);
const scale=120/img.width;
canvas.width=120;
canvas.height=img.height*scale;
const ctx=canvas.getContext(&#39;2d&#39;);
ctx.drawImage(img,0,0,canvas.width,canvas.height);
const data=canvas.toDataURL(&#39;image/jpeg&#39;,0.7);
container.innerHTML=`&lt;img src=&quot;${data}&quot; class=&quot;preview-img&quot;&gt;`;
hidden.value=data;
};
img.src=e.target.result;
};
reader.readAsDataURL(input.files[0]);
}
}

/* ---------------- ADD CHILD ---------------- */

let nodeCount=1;

function addChild(parentId){

nodeCount++;

const parent=document.querySelector(`[data-node-id=&quot;${parentId}&quot;]`);
const parentLevel=parseInt(parent.dataset.level||1);
const newLevel=parentLevel+1;

const html=`
&lt;div class=&quot;node-input-group&quot; data-node-id=&quot;${nodeCount}&quot; data-level=&quot;${newLevel}&quot;&gt;
&lt;input class=&quot;link-text text-xs mb-1&quot; value=&quot;leads to&quot;&gt;
&lt;div class=&quot;node-card relative&quot;&gt;
&lt;button onclick=&quot;deleteNode(&#39;${nodeCount}&#39;)&quot; class=&quot;absolute top-2 right-2 text-red-400 hover:text-red-600 font-bold text-lg leading-none&quot;&gt;×&lt;/button&gt;
&lt;textarea class=&quot;node-text w-full p-2 border rounded mb-2 text-sm&quot; rows=&quot;2&quot; placeholder=&quot;Enter multiline text...&quot;&gt;&lt;/textarea&gt;
&lt;input type=&quot;file&quot; onchange=&quot;handleImgPreview(this)&quot; class=&quot;text-xs w-full&quot;&gt;
&lt;input type=&quot;hidden&quot; class=&quot;node-image-data&quot;&gt;
&lt;div class=&quot;img-preview-container mt-2&quot;&gt;&lt;/div&gt;
&lt;button onclick=&quot;addChild(&#39;${nodeCount}&#39;)&quot; class=&quot;text-blue-500 text-xs mt-2 font-semibold&quot;&gt;+ Add Child&lt;/button&gt;
&lt;/div&gt;
&lt;div class=&quot;children-container ml-6&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
`;

parent.querySelector(&#39;.children-container&#39;).insertAdjacentHTML(&#39;beforeend&#39;,html);
}

/* ---------------- DELETE NODE ---------------- */

function deleteNode(nodeId) {
if(nodeId === &#39;1&#39;) return alert(&quot;Cannot delete the root node.&quot;);

const node = document.querySelector(`[data-node-id=&quot;${nodeId}&quot;]`);
if(node &amp;&amp; confirm(&quot;Delete this node and all its child components?&quot;)) {
node.remove();
generateChart(); 
}
}

/* ---------------- GENERATE ---------------- */

async function generateChart(){

const root=document.querySelector(&#39;[data-node-id=&quot;1&quot;]&#39;);
if(!root) return;

const orientation = document.getElementById(&quot;chart-layout&quot;).value || &quot;TD&quot;;
let def=`graph ${orientation}\n`;

let styleDef=&quot;&quot;;
const visited=new Set();

function clean(text){
return text
.replace(/&quot;/g,&quot;&#39;&quot;)
.replace(/[&lt;&gt;]/g,&quot;&quot;)
.replace(/[\[\]\(\)\{\}]/g,&quot;&quot;)
.replace(/[:;|]/g,&quot;-&quot;)
.replace(/\n/g, &quot;&lt;br/&gt;&quot;);
}

function hslToHex(h, s, l) {
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = n =&gt; {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, &#39;0&#39;);
};
return `#${f(0)}${f(8)}${f(4)}`;
}

function traverse(el){

const id=el.dataset.nodeId;

if(!visited.has(id)){
visited.add(id);

const text=clean(el.querySelector(&#39;.node-text&#39;).value||&quot;Node&quot;);
const img=el.querySelector(&#39;.node-image-data&#39;).value;

// Force structural sharp rectangle shape configurations uniformly across all tier blocks
let shapeStart=&quot;[&quot;, shapeEnd=&quot;]&quot;;

const labelContent = `&lt;div style=&#39;max-width:220px; white-space:normal; word-wrap:break-word; text-align:center; padding:4px;&#39;&gt;${img ? `&lt;img src=&#39;${img}&#39; width=&#39;40&#39; style=&#39;display:inline-block; margin-bottom:4px;&#39;/&gt;&lt;br/&gt;` : &#39;&#39;}${text}&lt;/div&gt;`;

def+=`n${id}${shapeStart}&quot;${labelContent}&quot;${shapeEnd}\n`;

const hue = (parseInt(id) * 137.5) % 360; 
const fillHex = hslToHex(hue, 80, 93);
const strokeHex = hslToHex(hue, 75, 40);
styleDef += `style n${id} fill:${fillHex},stroke:${strokeHex},stroke-width:2px\n`;
}

const children=el.querySelectorAll(&#39;:scope &gt; .children-container &gt; .node-input-group&#39;);

children.forEach(child=&gt;{
const linkEl=child.querySelector(&#39;.link-text&#39;);
const link=linkEl?clean(linkEl.value):&quot;link&quot;;

def+=`n${id}--&quot;${link}&quot;--&gt;n${child.dataset.nodeId}\n`;

traverse(child);
});
}

traverse(root);
def += &quot;\n&quot; + styleDef;

try{
await mermaid.parse(def);
const {svg}=await mermaid.render(&quot;m&quot;+Date.now(),def);
document.getElementById(&#39;mermaid-render&#39;).innerHTML=svg;
}catch(e){
console.error(def,e);
alert(&quot;Render error&quot;);
}
}

/* ---------------- DB (INDEXED DB) ---------------- */

let db;
const req=indexedDB.open(&quot;FlowDB&quot;,1);

req.onupgradeneeded=e=&gt;{
e.target.result.createObjectStore(&quot;charts&quot;,{keyPath:&quot;name&quot;});
};

req.onsuccess=e=&gt;{
db=e.target.result;
updateDropdown();
};

function updateDropdown(){
const d=document.getElementById(&quot;saved-charts-dropdown&quot;);
const store=db.transaction(&quot;charts&quot;,&quot;readonly&quot;).objectStore(&quot;charts&quot;);

store.getAllKeys().onsuccess=e=&gt;{
d.innerHTML=&#39;&lt;option value=&quot;&quot;&gt;-- Load --&lt;/option&gt;&#39;;
e.target.result.forEach(k=&gt;{
d.innerHTML+=`&lt;option&gt;${k}&lt;/option&gt;`;
});
};
}

function serialize(el){
return{
id:el.dataset.nodeId,
level:el.dataset.level,
text:el.querySelector(&#39;.node-text&#39;).value,
img:el.querySelector(&#39;.node-image-data&#39;).value,
link:el.querySelector(&#39;.link-text&#39;)?.value||&quot;&quot;,
children:[...el.querySelector(&#39;:scope &gt; .children-container&#39;).children].map(serialize)
};
}

function saveToDB(){
const name=document.getElementById(&quot;chart-name&quot;).value;
if(!name)return alert(&quot;Name required&quot;);

const layout=document.getElementById(&quot;chart-layout&quot;).value; 
const treeData=serialize(document.querySelector(&#39;[data-node-id=&quot;1&quot;]&#39;));

db.transaction(&quot;charts&quot;,&quot;readwrite&quot;).objectStore(&quot;charts&quot;).put({name, layout, data: treeData});

alert(&quot;Saved to IndexedDB successfully&quot;);
updateDropdown();
}

function loadChart(){
const name=document.getElementById(&quot;saved-charts-dropdown&quot;).value;
if(!name)return;

db.transaction(&quot;charts&quot;,&quot;readonly&quot;).objectStore(&quot;charts&quot;).get(name).onsuccess=e=&gt;{

const c=e.target.result;
const container=document.getElementById(&quot;builder-container&quot;);
container.innerHTML=&quot;&quot;;

function render(d,parent){

nodeCount=Math.max(nodeCount,parseInt(d.id));

const deleteBtn = d.id != 1 ? `&lt;button onclick=&quot;deleteNode(&#39;${d.id}&#39;)&quot; class=&quot;absolute top-2 right-2 text-red-400 hover:text-red-600 font-bold text-lg leading-none&quot;&gt;×&lt;/button&gt;` : &#39;&#39;;

const html=`
&lt;div class=&quot;node-input-group&quot; data-node-id=&quot;${d.id}&quot; data-level=&quot;${d.level}&quot;&gt;
${d.id != 1 ? `&lt;input class=&quot;link-text text-xs mb-1&quot; value=&quot;${d.link}&quot;&gt;` : &#39;&#39;}
&lt;div class=&quot;node-card relative&quot;&gt;
${deleteBtn}
&lt;textarea class=&quot;node-text w-full p-2 border rounded mb-2 text-sm&quot; rows=&quot;2&quot;&gt;${d.text}&lt;/textarea&gt;
&lt;input type=&quot;file&quot; onchange=&quot;handleImgPreview(this)&quot; class=&quot;text-xs w-full&quot;&gt;
&lt;input type=&quot;hidden&quot; class=&quot;node-image-data&quot; value=&quot;${d.img}&quot;&gt;
&lt;div class=&quot;img-preview-container mt-2&quot;&gt;${d.img?`&lt;img src=&quot;${d.img}&quot; class=&quot;preview-img&quot;&gt;`:&#39;&#39;}&lt;/div&gt;
&lt;button onclick=&quot;addChild(&#39;${d.id}&#39;)&quot; class=&quot;text-blue-500 text-xs mt-2 font-semibold&quot;&gt;+ Add Child&lt;/button&gt;
&lt;/div&gt;
&lt;div class=&quot;children-container ml-6&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
`;

parent.insertAdjacentHTML(&quot;beforeend&quot;,html);

const newNode=parent.lastElementChild;

d.children.forEach(ch=&gt;render(ch,newNode.querySelector(&#39;.children-container&#39;)));
}

render(c.data,container);
document.getElementById(&quot;chart-name&quot;).value = name;
document.getElementById(&quot;chart-layout&quot;).value = c.layout || &quot;TD&quot;; 
generateChart();
};
}

function deleteChart(){
const name=document.getElementById(&quot;saved-charts-dropdown&quot;).value;
if(name &amp;&amp; confirm(&quot;Delete this chart permanently from DB?&quot;)){
db.transaction(&quot;charts&quot;,&quot;readwrite&quot;).objectStore(&quot;charts&quot;).delete(name);
location.reload();
}
}

/* ---------------- EXPORT ---------------- */

function exportSVG(){
const svg=document.querySelector(&quot;#mermaid-render svg&quot;);
if(!svg)return alert(&quot;Preview first&quot;);

let chartName = document.getElementById(&quot;chart-name&quot;).value.trim();
if(!chartName) {
    chartName = &quot;flowchart&quot;;
} else {
    chartName = chartName.replace(/[^a-zA-Z0-9-_ ]/g, &quot;&quot;).replace(/\s+/g, &quot;_&quot;);
}

const today = new Date();
const yyyy = today.getFullYear();
const mm = String(today.getMonth() + 1).padStart(2, &#39;0&#39;);
const dd = String(today.getDate()).padStart(2, &#39;0&#39;);
const dateStr = `${yyyy}-${mm}-${dd}`;

const data=new XMLSerializer().serializeToString(svg);
const blob=new Blob([data],{type:&quot;image/svg+xml&quot;});

const a=document.createElement(&quot;a&quot;);
a.href=URL.createObjectURL(blob);
a.download=`${chartName}_${dateStr}.svg`;
a.click();
}

&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/04/flowchart-generating-tool.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-2032883736862475092</guid><pubDate>Sat, 18 Apr 2026 08:40:00 +0000</pubDate><atom:updated>2026-06-23T14:06:44.521+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><category domain="http://www.blogger.com/atom/ns#">Software</category><category domain="http://www.blogger.com/atom/ns#">Tender</category><title>DTP data</title><description>&lt;style&gt;
        body {
            font-family: &#39;Segoe UI&#39;, Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: #2d3748;
            max-width: 900px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f7fafc;
        }
        header {
            background-color: #2c5282;
            color: white;
            padding: 24px;
            border-radius: 8px;
            margin-bottom: 30px;
            text-align: center;
            box-shadow: 0 4px 6px rgba(0,0,0,0.05);
        }
        h1 { margin: 0; font-size: 26px; font-weight: 600; }
        h2 { color: #2b6cb0; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; margin-top: 35px; }
        h3 { color: #4a5568; margin-top: 20px; }
        code {
            background-color: #edf2f7;
            padding: 2px 6px;
            border-radius: 4px;
            font-family: Menlo, Monaco, Consolas, monospace;
            font-size: 0.9em;
            color: #805ad5;
        }
        .info-box {
            background-color: #ebf8ff;
            border-left: 4px solid #3182ce;
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 8px 8px 0;
        }
        .warning-box {
            background-color: #fffaf0;
            border-left: 4px solid #dd6b20;
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 8px 8px 0;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
            background: white;
            box-shadow: 0 1px 3px rgba(0,0,0,0.05);
        }
        th, td {
            border: 1px solid #e2e8f0;
            padding: 12px;
            text-align: left;
        }
        th { background-color: #edf2f7; color: #4a5568; font-weight: 600; }
        ul, ol { padding-left: 22px; }
        li { margin-bottom: 8px; }
    &lt;/style&gt;
&lt;div id=&quot;calculator-container&quot; style=&quot;font-family: &#39;Segoe UI&#39;, Arial, sans-serif; max-width: 950px; margin: auto; padding: 20px; border: 1px solid #ccc; border-radius: 10px; background: #fff; color: #333;&quot;&gt;
    &lt;h2 style=&quot;text-align: center; color: #0056b3;&quot;&gt;Infrastructure Project Manager (Local + Sync)&lt;/h2&gt;
    
    &lt;div style=&quot;background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 20px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap;&quot;&gt;
        &lt;label&gt;&lt;strong&gt;Select Project:&lt;/strong&gt;&lt;/label&gt;
        &lt;select id=&quot;projectSelect&quot; onchange=&quot;loadProject()&quot; style=&quot;padding: 8px; flex-grow: 1; border: 1px solid #0056b3; border-radius: 4px;&quot;&gt;
            &lt;option value=&quot;&quot;&gt;-- New Project --&lt;/option&gt;
        &lt;/select&gt;
        &lt;button onclick=&quot;exportJSON()&quot; style=&quot;padding: 8px 12px; background: #6c757d; color: white; border: none; border-radius: 4px; cursor: pointer;&quot;&gt;Export JSON&lt;/button&gt;
        &lt;button onclick=&quot;document.getElementById(&#39;importFile&#39;).click()&quot; style=&quot;padding: 8px 12px; background: #6c757d; color: white; border: none; border-radius: 4px; cursor: pointer;&quot;&gt;Import JSON&lt;/button&gt;
        &lt;input type=&quot;file&quot; id=&quot;importFile&quot; style=&quot;display:none&quot; onchange=&quot;importJSON(event)&quot;&gt;
    &lt;/div&gt;

    &lt;div style=&quot;display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; margin-bottom: 20px;&quot;&gt;
        &lt;div&gt;&lt;label&gt;Project Name:&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;projectName&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Total Cost (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;totalWork&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Schedule &quot;A&quot; (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;schA&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Asphalt (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;asphalt&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Pipe (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;pipe&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Cement (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;cement&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Steel (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;steel&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Royalty (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;royalty&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Labour (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;labour&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;POL (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;pol&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Material (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;material&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
      	&lt;div&gt;&lt;label&gt;Lab Testing (₹):&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;lab&quot; oninput=&quot;calculate()&quot; style=&quot;width:100%; padding:8px;&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;div style=&quot;background: #e7f3ff; padding: 15px; border-radius: 8px; margin-bottom: 20px; display: flex; justify-content: space-between; flex-wrap: wrap;&quot;&gt;
        &lt;span&gt;&lt;strong&gt;W (Excl. Materials):&lt;/strong&gt; ₹&lt;span id=&quot;excludedCostDisplay&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
        &lt;span&gt;&lt;strong&gt;K1:&lt;/strong&gt; &lt;span id=&quot;lPct&quot;&gt;0&lt;/span&gt;%&lt;/span&gt;
        &lt;span&gt;&lt;strong&gt;K2:&lt;/strong&gt; &lt;span id=&quot;pPct&quot;&gt;0&lt;/span&gt;%&lt;/span&gt;
        &lt;span&gt;&lt;strong&gt;K3:&lt;/strong&gt; &lt;span id=&quot;mPct&quot;&gt;0&lt;/span&gt;%&lt;/span&gt;
        &lt;div id=&quot;warning&quot; style=&quot;color: red; font-weight: bold; width: 100%; margin-top: 5px;&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;button id=&quot;saveBtn&quot; onclick=&quot;saveToDB()&quot; style=&quot;width: 100%; padding: 12px; background: #007bff; color: white; font-weight: bold; border: none; border-radius: 5px; cursor: pointer;&quot;&gt;Save / Update &amp; Sync to Cloud&lt;/button&gt;

    &lt;h4 style=&quot;margin-top:30px;&quot;&gt;Locally Saved Projects&lt;/h4&gt;
    &lt;div style=&quot;overflow: auto; max-height: 350px; border: 1px solid #ddd; border-radius: 5px;&quot;&gt;
        &lt;table id=&quot;localTable&quot; style=&quot;width: 100%; border-collapse: collapse; min-width: 800px;&quot;&gt;
            &lt;thead style=&quot;background: #333; color: white; position: sticky; top: 0;&quot;&gt;
                &lt;tr&gt;
                    &lt;th style=&quot;padding: 10px;&quot;&gt;Project Name&lt;/th&gt;
                    &lt;th&gt;W (Excluded)&lt;/th&gt;
                    &lt;th&gt;K1%&lt;/th&gt;
                    &lt;th&gt;K2%&lt;/th&gt;
                    &lt;th&gt;K3%&lt;/th&gt;
                    &lt;th&gt;Actions&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody style=&quot;text-align: center;&quot;&gt;&lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;header&gt;
    &lt;h1&gt;User Guide: Project Cost Estimator &amp; Cloud Sync Tool&lt;/h1&gt;
    &lt;p&gt;Operational documentation for local cost management, mathematical verification, and automated cloud logging&lt;/p&gt;
&lt;/header&gt;

&lt;section&gt;
    &lt;h2&gt;1. Overview&lt;/h2&gt;
    &lt;p&gt;This program is a dedicated construction estimation utility designed to evaluate project budgets, calculate baseline overhead dynamics, and log historical data. It utilizes a zero-latency hybrid infrastructure: records are compiled securely on your device while simultaneously running a background sync routine with an external Google Sheets database.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;2. System Components &amp; Flow&lt;/h2&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;Local Storage Core (IndexedDB):&lt;/strong&gt; Powered by an internal database called &lt;code&gt;ProjectDB&lt;/code&gt;. It writes directly to your browser&#39;s persistent storage engine, preventing data loss even if you refresh or close the page.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Live Cloud Sync:&lt;/strong&gt; Submits an integrated JSON payload over a secure webhook architecture to a Google Apps Script macro address (&lt;code&gt;SCRIPT_URL&lt;/code&gt;) to populate standard data cell spreadsheets automatically.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Automatic Balance Verification:&lt;/strong&gt; Evaluates structural component inputs dynamically against calculated residual cost variables to flag proportioning imbalances instantly.&lt;/li&gt;
    &lt;/ul&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;3. Operating Instructions&lt;/h2&gt;

    &lt;h3&gt;Step 1: Setting Up Your Workspace&lt;/h3&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;Initiate a New Project:&lt;/strong&gt; Keep the main dropdown element marked as &lt;code&gt;-- New Project --&lt;/code&gt; and enter a unique descriptor in the &lt;strong&gt;Project Name&lt;/strong&gt; field box.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Load Existing Record:&lt;/strong&gt; Click the selection drop-down panel. Selecting an item calls the internal &lt;code&gt;loadProject()&lt;/code&gt; framework to read database logs and accurately re-populate the form layout.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3&gt;Step 2: Inputting Financial Vectors&lt;/h3&gt;
    &lt;p&gt;Provide baseline cost values inside the interface form boxes. Numerical entries are automatically aggregated to complete the calculation steps:&lt;/p&gt;
    &lt;ol&gt;
        &lt;li&gt;&lt;strong&gt;Total Work Cost:&lt;/strong&gt; The overall gross cap structural budget estimation value.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Material Costs:&lt;/strong&gt; Individual structural metrics representing specialized line expenditures (Asphalt, Pipe, Cement, and Steel line-items).&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Deductions &amp;amp; Fixed Costs:&lt;/strong&gt; Fixed charges including Royalty values and flat Labor line costs.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3&gt;Step 3: Calculating Excluded Costs and Proportions&lt;/h3&gt;
    &lt;p&gt;When financial values are updated, the application triggers its &lt;code&gt;calculate()&lt;/code&gt; matrix engine:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;strong&gt;Excluded Cost Calculation:&lt;/strong&gt; The calculator identifies the core project index through the following formula:
            &lt;br&gt;&lt;code&gt;Excluded Cost = Total Work - (Asphalt + Pipe + Cement + Steel) - Royalty - Labor&lt;/code&gt;
        &lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Proportional Distributions:&lt;/strong&gt; If your net excluded baseline value remains positive, the system evaluates the internal proportions of your secondary allocations (Labor, POL, and Materials) relative to that value.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;div class=&quot;warning-box&quot;&gt;
        &lt;strong&gt;Proportional Distribution Warning:&lt;/strong&gt; The system automatically verifies that the total percentage split equals 100%. If the aggregate total deviates from 100% by more than 0.05%, a warning alert will be displayed: &lt;code&gt;⚠️ Total: [Calculated Value]%&lt;/code&gt;. Re-adjust your inputs until the error alert disappears.
    &lt;/div&gt;

    &lt;h3&gt;Step 4: Commit Changes &amp;amp; Trigger Cloud Sync&lt;/h3&gt;
    &lt;p&gt;Once your values are finalized, click the &lt;strong&gt;Save&lt;/strong&gt; action control.&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;The system packages all form values alongside your calculated proportion metrics.&lt;/li&gt;
        &lt;li&gt;The system updates your browser database file. Once verified, a non-blocking background &lt;code&gt;POST&lt;/code&gt; request transmits the dataset directly to your designated cloud spreadsheet dashboard.&lt;/li&gt;
    &lt;/ul&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;4. Control Functions Quick Reference&lt;/h2&gt;
    &lt;table&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th&gt;Interface Control Trigger&lt;/th&gt;
                &lt;th&gt;Underlying Javascript Macro&lt;/th&gt;
                &lt;th&gt;Operational Consequence&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Save to DB&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;saveToDB()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Saves data locally, refreshes user interface tables, and transmits a mirror entry out to the designated Google Sheets cloud endpoint.&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Edit (Table Row Button)&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;editProject(name)&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Queries target indexes by name and populates active editing views with historical data metrics.&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Export JSON&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;exportJSON()&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Compiles all browser database files into a standard plain text file format, downloading it as &lt;code&gt;projects_backup.json&lt;/code&gt;.&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Import Data File&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;importJSON(event)&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Reads an uploaded configuration backup array, merges records safely over matching local storage indexes, and updates your user interface.&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;5. Technical Safety &amp;amp; Operational Integrity&lt;/h2&gt;
    &lt;div class=&quot;info-box&quot;&gt;
        &lt;strong&gt;Data Retention Guidelines:&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;Cross-Device Access:&lt;/strong&gt; Local storage is limited to the current browser profile on your device. To populate fields across different workstations, use the built-in &lt;strong&gt;Export/Import&lt;/strong&gt; options to migrate data files manually.&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Data Security:&lt;/strong&gt; The integration features a fire-and-forget sync utility (&lt;code&gt;no-cors&lt;/code&gt; mode). This architecture ensures rapid database updates without letting remote connection drops freeze your active browser tab.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;
&lt;/section&gt;

&lt;script&gt;
const SCRIPT_URL = &quot;https://script.google.com/macros/s/AKfycbwMT8V6XeFs0GKDblgwDjPR4fPr9f59haxW4FGrFzWAA4Szx0-RTyq6Gh2dH6Mvn5Hh/exec&quot;;
let db;

// 1. Initialize IndexedDB
const request = indexedDB.open(&quot;ProjectDB&quot;, 1);
request.onupgradeneeded = (e) =&gt; {
    db = e.target.result;
    db.createObjectStore(&quot;projects&quot;, { keyPath: &quot;projectName&quot; });
};
request.onsuccess = (e) =&gt; {
    db = e.target.result;
    refreshUI();
};

function getVal(id) { return parseFloat(document.getElementById(id).value) || 0; }

function calculate() {
    const total = getVal(&#39;totalWork&#39;);
    const materialsSum = getVal(&#39;asphalt&#39;) + getVal(&#39;pipe&#39;) + getVal(&#39;cement&#39;) + getVal(&#39;steel&#39;);
    const excluded = total - materialsSum - getVal(&#39;royalty&#39;) - getVal(&#39;lab&#39;);
    document.getElementById(&#39;excludedCostDisplay&#39;).innerText = excluded.toLocaleString(&#39;en-IN&#39;);
    
    if (excluded &gt; 0) {
        const l = (getVal(&#39;labour&#39;) / excluded * 100).toFixed(2);
        const p = (getVal(&#39;pol&#39;) / excluded * 100).toFixed(2);
        const m = (getVal(&#39;material&#39;) / excluded * 100).toFixed(2);
        document.getElementById(&#39;lPct&#39;).innerHTML = l;
        document.getElementById(&#39;pPct&#39;).innerHTML = p;
        document.getElementById(&#39;mPct&#39;).innerHTML = m;
        
        const check = parseFloat(l) + parseFloat(p) + parseFloat(m);
        document.getElementById(&#39;warning&#39;).innerHTML = Math.abs(check - 100) &gt; 0.05 ? `⚠️ Total: ${check.toFixed(2)}%` : &quot;&quot;;
    }
}

// 2. Save Data (Local + Cloud Sync)
function saveToDB() {
    const projectName = document.getElementById(&#39;projectName&#39;).value;
    if (!projectName) return alert(&quot;Enter Project Name&quot;);

    const data = {
        projectName, totalWork: getVal(&#39;totalWork&#39;), schA: getVal(&#39;schA&#39;),
        asphalt: getVal(&#39;asphalt&#39;), pipe: getVal(&#39;pipe&#39;), cement: getVal(&#39;cement&#39;),
        steel: getVal(&#39;steel&#39;), royalty: getVal(&#39;royalty&#39;), labour: getVal(&#39;labour&#39;),
        pol: getVal(&#39;pol&#39;), material: getVal(&#39;material&#39;),
        excludedCost: document.getElementById(&#39;excludedCostDisplay&#39;).innerHTML,
        labourPct: document.getElementById(&#39;lPct&#39;).innerHTML,
        polPct: document.getElementById(&#39;pPct&#39;).innerHTML,
        materialPct: document.getElementById(&#39;mPct&#39;).innerHTML
    };

    const transaction = db.transaction([&quot;projects&quot;], &quot;readwrite&quot;);
    transaction.objectStore(&quot;projects&quot;).put(data);
    
    transaction.oncomplete = () =&gt; {
        refreshUI();
        // Background sync to Google Sheets
        fetch(SCRIPT_URL, { method: &#39;POST&#39;, mode: &#39;no-cors&#39;, body: JSON.stringify(data) });
        alert(&quot;Saved locally and synced to Google Sheets!&quot;);
    };
}

// 3. UI Refreshes
function refreshUI() {
    const select = document.getElementById(&#39;projectSelect&#39;);
    const tbody = document.getElementById(&#39;localTable&#39;).getElementsByTagName(&#39;tbody&#39;)[0];
    select.innerHTML = &#39;&lt;option value=&quot;&quot;&gt;-- New Project --&lt;/option&gt;&#39;;
    tbody.innerHTML = &quot;&quot;;

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).getAll().onsuccess = (e) =&gt; {
        e.target.result.forEach(proj =&gt; {
            // Fill Dropdown
            let opt = document.createElement(&quot;option&quot;);
            opt.value = proj.projectName;
            opt.innerText = proj.projectName;
            select.appendChild(opt);

            // Fill Table
            let row = tbody.insertRow();
            row.innerHTML = `&lt;td&gt;${proj.projectName}&lt;/td&gt;&lt;td&gt;${proj.excludedCost}&lt;/td&gt;&lt;td&gt;${proj.labourPct}%&lt;/td&gt;&lt;td&gt;${proj.polPct}%&lt;/td&gt;&lt;td&gt;${proj.materialPct}%&lt;/td&gt;
            &lt;td&gt;&lt;button onclick=&quot;editProject(&#39;${proj.projectName}&#39;)&quot;&gt;Edit&lt;/button&gt;&lt;/td&gt;`;
        });
    };
}

function editProject(name) {
    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(name).onsuccess = (e) =&gt; {
        const p = e.target.result;
        document.getElementById(&#39;projectName&#39;).value = p.projectName;
        document.getElementById(&#39;totalWork&#39;).value = p.totalWork;
        document.getElementById(&#39;schA&#39;).value = p.schA;
        document.getElementById(&#39;asphalt&#39;).value = p.asphalt;
        document.getElementById(&#39;pipe&#39;).value = p.pipe;
        document.getElementById(&#39;cement&#39;).value = p.cement;
        document.getElementById(&#39;steel&#39;).value = p.steel;
        document.getElementById(&#39;royalty&#39;).value = p.royalty;
        document.getElementById(&#39;labour&#39;).value = p.labour;
        document.getElementById(&#39;pol&#39;).value = p.pol;
        document.getElementById(&#39;material&#39;).value = p.material;
        calculate();
    };
}

function loadProject() {
    const val = document.getElementById(&#39;projectSelect&#39;).value;
    if (val) editProject(val);
}

// 4. Import / Export
function exportJSON() {
    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).getAll().onsuccess = (e) =&gt; {
        const blob = new Blob([JSON.stringify(e.target.result)], {type: &quot;application/json&quot;});
        const url = URL.createObjectURL(blob);
        const a = document.createElement(&quot;a&quot;);
        a.href = url;
        a.download = &quot;projects_backup.json&quot;;
        a.click();
    };
}

function importJSON(event) {
    const reader = new FileReader();
    reader.onload = (e) =&gt; {
        const data = JSON.parse(e.target.result);
        const tx = db.transaction([&quot;projects&quot;], &quot;readwrite&quot;);
        data.forEach(item =&gt; tx.objectStore(&quot;projects&quot;).put(item));
        tx.oncomplete = () =&gt; { refreshUI(); alert(&quot;Imported successfully!&quot;); };
    };
    reader.readAsText(event.target.files[0]);
}
&lt;/script&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/04/dtp-data.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-7796120572573275009</guid><pubDate>Fri, 17 Apr 2026 02:26:00 +0000</pubDate><atom:updated>2026-04-17T13:54:20.752+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><title>Maharashtra Forest Land Diversion 2026: Complete KML + Checklist + Tree Maliki Guide for PWD Engineers | PARIVESH Portal</title><description>&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js&quot;&gt;&lt;/script&gt;
    &lt;script&gt;
        mermaid.initialize({ startOnLoad: true, theme: &#39;neutral&#39; });
    &lt;/script&gt;
&lt;style&gt;
    @import url(&#39;https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari:wght@400;500;700&amp;display=swap&#39;);
    
    body {
        font-family: &#39;Noto Sans Devanagari&#39;, &#39;Segoe UI&#39;, Arial, sans-serif;
        line-height: 1.7;
        color: #333;
        max-width: 1100px;
        margin: 0 auto;
        padding: 20px;
        background: #f9f9f9;
    }
    
    h1 {
        color: #006400;
        text-align: center;
        font-size: 2.4em;
        margin-bottom: 10px;
    }
    
    h2 {
        color: #006400;
        border-bottom: 3px solid #8FBC8F;
        padding-bottom: 8px;
        margin-top: 40px;
    }
    
    h3 {
        color: #228B22;
    }
    
    table {
        width: 100%;
        border-collapse: collapse;
        margin: 20px 0;
        background: white;
        box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    }
    
    th, td {
        border: 1px solid #8FBC8F;
        padding: 12px;
        text-align: left;
        vertical-align: top;
    }
    
    th {
        background: yellow;
        color: blue;
    }
    
    ul {
        background: #f0f8f0;
        padding: 20px;
        border-radius: 8px;
    }
    
    li {
        margin-bottom: 10px;
    }
    
    .highlight {
        background: #fffacd;
        padding: 15px;
        border-left: 6px solid #006400;
        font-weight: bold;
    }
    
    .note {
        font-size: 0.95em;
        color: #555;
        font-style: italic;
    }
    
    .author {
        text-align: center;
        margin: 40px 0;
        font-size: 1.1em;
        color: #006400;
    }
    
    pre {
        background: #f4f4f4;
        padding: 15px;
        border-radius: 6px;
        overflow-x: auto;
    }
    
    .new-section {
        border-top: 4px dashed #8FBC8F;
        padding-top: 30px;
        margin-top: 40px;
    }
    
    /* Certificate &amp; Checklist specific styles */
    :root {
        --page-width: 210mm;
        --page-height: 297mm;
    }
    
    .container {
        max-width: 1200px;
        margin: 0 auto;
    }
    
    .checklist {
        background: white;
        border: 2px solid #000;
        margin-bottom: 40px;
        padding: 20px;
        box-shadow: 0 4px 12px rgba(0,0,0,0.1);
    }
    
    .checklist table {
        width: 100%;
        border-collapse: collapse;
        margin: 15px 0;
    }
    
    .checklist th, .checklist td {
        border: 1px solid #000;
        padding: 10px 12px;
        text-align: left;
        vertical-align: top;
        font-size: 15px;
    }
    
    .checklist th {
        background: #f0f0f0;
        font-weight: 700;
        text-align: center;
    }
    
    .yes-no {
        text-align: center;
        width: 60px;
    }
    
    .remark {
        width: 150px;
    }
    
    .section-title {
        background: #000;
        color: white;
        padding: 10px 20px;
        margin-bottom: 15px;
        font-size: 20px;
    }
    
    /* Certificate Page - Each certificate on separate printable page */
    .certificate-page {
        width: 780px;                  /* ← REDUCED from 210mm to fit Blogger window */
        max-width: 100%;               /* Responsive on mobile */
        min-height: 950px;             /* Keeps visual A4 proportion */
        margin: 30px auto;
        padding: 25mm 20mm;
        background: white;
        border: 3px solid #000;
        box-shadow: 0 10px 30px rgba(0,0,0,0.2);
        position: relative;
        page-break-after: always;
        box-sizing: border-box;
        overflow: hidden;
    }

    .certificate-page:last-child { page-break-after: avoid; }

    .certificate-content {
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
    }

    .certificate-header {
        text-align: center;
        font-size: 18px;
        font-weight: 700;
        margin-bottom: 20px;
        border-bottom: 2px solid #000;
        padding-bottom: 10px;
    }

    .certificate-title {
        text-align: center;
        font-size: 22px;
        font-weight: 700;
        margin: 25px 0 30px 0;
        line-height: 1.3;
    }

    .signature-block {
        margin-top: 60px;
        display: flex;
        justify-content: space-between;
        align-items: flex-end;
    }

    .signature-left { text-align: left; }
    .signature-right { text-align: right; }

    .page-number {
        position: absolute;
        bottom: 12mm;
        right: 20mm;
        font-size: 12px;
        color: #555;
    }

    /* Print - Full A4 size (unchanged) */
    @media print {
        body { background: white; padding: 0; max-width: none; }
        .container { max-width: none; }
        .checklist { box-shadow: none; margin: 0; page-break-inside: avoid; }
      	.header { background: #006400; color: white; }
        .mermaid-container { border: 2px solid #006400; box-shadow: none; }
        .certificate-page {
            width: 210mm !important;           /* Full A4 width when printing */
            max-width: 210mm !important;
            min-height: 297mm !important;
            margin: 0 auto;
            box-shadow: none;
            border: 2px solid #000;
            page-break-after: always;
          
            
        }
        .certificate-page:last-child { page-break-after: avoid; }
    }
  .header {
            background: #006400;
            color: white;
            padding: 20px;
            text-align: center;
            box-shadow: 0 4px 12px rgba(0,0,0,0.2);
        }
        .header h1 {
            margin: 0;
            font-size: 2.2em;
        }
        .header p {
            margin: 8px 0 0;
            font-size: 1.1em;
            opacity: 0.95;
        }
        .container {
            max-width: 1300px;
            margin: 30px auto;
            padding: 0 20px;
        }
        .card {
            background: white;
            border-radius: 12px;
            box-shadow: 0 8px 25px rgba(0,0,0,0.15);
            padding: 25px;
            margin-bottom: 30px;
        }
        .mermaid-container {
            background: #fff;
            border: 3px solid #006400;
            border-radius: 12px;
            padding: 20px;
            overflow: auto;
        }
        .controls {
            display: flex;
            gap: 12px;
            justify-content: center;
            margin: 20px 0;
            flex-wrap: wrap;
        }
        button {
            padding: 12px 24px;
            font-size: 1em;
            border: none;
            border-radius: 8px;
            background: #006400;
            color: white;
            cursor: pointer;
            transition: all 0.3s;
        }
        button:hover {
            background: #004d00;
            transform: translateY(-2px);
        }
        .info {
            font-size: 0.95em;
            line-height: 1.6;
            background: #f8fff8;
            padding: 20px;
            border-left: 6px solid #006400;
            border-radius: 8px;
        }
        footer {
            text-align: center;
            padding: 20px;
            color: #555;
            font-size: 0.9em;
        }
&lt;/style&gt;

&lt;h1&gt;Maharashtra Forest Land Diversion 2026:&lt;br&gt;Complete Practical Guide for Civil Engineers&lt;/h1&gt;
&lt;p style=&quot;text-align:center; font-size:1.3em; color:#006400;&quot;&gt;&lt;strong&gt;KML File Guidelines + 1-Hectare FRA Checklist + Full FCA Checklist + Tree Ownership (Maliki) Documents for PARIVESH Portal&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;author&quot;&gt;
    &lt;strong&gt;By Yogendra — Civil / Structural Engineer | PWD Maharashtra&lt;/strong&gt;&lt;br&gt;
    &lt;small&gt;Practical insights for Road, EPC &amp;amp; Infrastructure projects involving forest clearance&lt;/small&gt;
&lt;/div&gt;

&lt;p&gt;As a Civil Engineer working on PWD and EPC projects in Maharashtra, one have to prepare forest diversion proposals. One small mistake in KML file, missing certificate or incomplete tree ownership documents can lead to automatic rejection on PARIVESH portal and months of delay.&lt;/p&gt;

&lt;p&gt;This article compiles the &lt;strong&gt;latest official guidelines&lt;/strong&gt; (November 2025) issued by the Principal Chief Conservator of Forests (Maharashtra) along with the complete checklists for small (≤1 ha) and regular FCA proposals — &lt;strong&gt;plus the full list of documents required for Tree Ownership (Maliki Prakaran) Certificate&lt;/strong&gt;. Everything you need in one place — ready to use for your next tender or DPR.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;
    &lt;strong&gt;Key Takeaway for PWD Engineers:&lt;/strong&gt; Always prepare KML in Polygon only, follow colour codes strictly, keep every map counter-signed by DCF + Surveyor + User Agency, and attach complete Tree Maliki documents whenever private/identified forest land or tree enumeration is involved. Area in KML properties must exactly match the proposed area.
&lt;/div&gt;

&lt;div class=&quot;header&quot;&gt;
    &lt;h1&gt;FRA Section 3(2) vs FCA 1980&lt;/h1&gt;
    &lt;p&gt;वन जमीन वळवण्याची मंजुरी प्रक्रिया (Maharashtra PWD &amp; EPC Road Projects)&lt;/p&gt;
&lt;/div&gt;

&lt;div class=&quot;mermaid-container&quot;&gt;
    &lt;div class=&quot;mermaid&quot; id=&quot;flowchart&quot;&gt;
flowchart TD
    A([&quot;Start: Road Project Identified&lt;br&gt;(PWD / User Agency)&quot;]) 
    --&gt; B{&quot;Proposed Forest Area?&quot;}

    B --&gt;|&quot;&lt; 1 Hectare &amp; Sec 3(2)&quot;| FRA[&quot;FRA Section 3(2)&lt;br&gt;Simplified Procedure&quot;]
    B --&gt;|&quot;&gt; 1 Hectare or Linear&quot;| FCA[&quot;FCA 1980 / Van Adhiniyam&lt;br&gt;Regular Procedure&quot;]

    subgraph FRA_Path [&quot;FRA Sec 3(2) - Fast Track&quot;]
        FRA --&gt; C1[&quot;Prepare Sample-K,&lt;br&gt;7/12 &amp; 1:50000 Map&quot;]
        C1 --&gt; C2[&quot;Gram Sabha Resolution&lt;br&gt;(50% Quorum)&quot;]
        C2 --&gt; C3[&quot;Tahsildar Certificate:&lt;br&gt;Non-Forest land unavailable&quot;]
        C3 --&gt; C4[&quot;Submit to RFO&quot;]
        C4 --&gt; C5[&quot;RFO: Sample-Kh + Inspection&quot;]
        C5 --&gt; C6[&quot;RFO Certificates:&lt;br&gt;Area/Court Case Check&quot;]
        C6 --&gt; C7[&quot;Forward to Territorial DCF&quot;]
        C7 --&gt; C8[&quot;DCF Approval - Final&quot;]
        C8 --&gt; END1([&quot;Forest Clearance Granted&quot;])
    end

    subgraph FCA_Path [&quot;FCA 1980 - Detailed Procedure&quot;]
        FCA --&gt; D1[&quot;Prepare KML,&lt;br&gt;NPV &amp; CA Undertakings&quot;]
        D1 --&gt; D2[&quot;Upload on PARIVESH (Form-A)&quot;]
        D2 --&gt; D3[&quot;Scrutiny by Nodal Officer&quot;]
        D3 --&gt; D4{&quot;Queries/EDS?&quot;}
        D4 --&gt;|Yes| D5[&quot;Agency Resubmits&quot;]
        D5 --&gt; D3
        D4 --&gt;|No| D6[&quot;Site Inspection &amp; Tree Enum&quot;]
        D6 --&gt; D7[&quot;Wildlife Clearance&lt;br&gt;(If Applicable)&quot;]
        D7 --&gt; D8[&quot;CA Land ID + NPV Payment&quot;]
        D8 --&gt; D9[&quot;DCF Recommendation (Part-II)&quot;]
        D9 --&gt; D10[&quot;PCCF Review &amp; State Forwarding&quot;]
        D10 --&gt; D11{&quot;Area &gt; 5 Ha?&quot;}
        D11 --&gt;|Yes| D12[&quot;PSC + State Stage-I&quot;]
        D11 --&gt;|No| D13[&quot;IRO - Stage-I In-principle&quot;]
        D12 --&gt; D13
        D13 --&gt; D14[&quot;Stage-I Approval&lt;br&gt;(Conditions)&quot;]
        D14 --&gt; D15[&quot;Compliance: Payment + Land&quot;]
        D15 --&gt; D16[&quot;Stage-II Final Approval&quot;]
        D16 --&gt; END2([&quot;Forest Clearance Granted&quot;])
    end

    END1 --&gt; Z([&quot;Project Can Proceed&quot;])
    END2 --&gt; Z

    %% Styling
    classDef fra fill:#e6ffe6,stroke:#006400,stroke-width:2px,color:#000;
    classDef fca fill:#fff0e6,stroke:#8B4513,stroke-width:2px,color:#000;
    class FRA_Path fra;
    class FCA_Path fca;
    &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;controls&quot;&gt;
    &lt;button onclick=&quot;copyMermaidCode()&quot;&gt;📋 Copy Mermaid Code&lt;/button&gt;
    &lt;button onclick=&quot;window.print()&quot;&gt;🖨️ Print / Save as PDF&lt;/button&gt;
&lt;/div&gt;

&lt;pre id=&quot;mermaidSource&quot; style=&quot;display:none;&quot;&gt;
flowchart TD
    A([&quot;Start: Road Project Identified&quot;]) --&gt; B{&quot;Forest Area?&quot;}
    B --&gt;|&quot;&lt; 1 Ha&quot;| FRA[&quot;FRA Sec 3(2)&quot;]
    B --&gt;|&quot;&gt; 1 Ha&quot;| FCA[&quot;FCA 1980&quot;]
    %% Simplified version for clipboard...
&lt;/pre&gt;

&lt;script&gt;
    function copyMermaidCode() {
        // This targets the text within the mermaid div before it renders, 
        // but since Mermaid clears it, we use the hidden pre tag for reliable copying.
        const code = document.getElementById(&#39;mermaidSource&#39;).innerText;
        navigator.clipboard.writeText(code).then(() =&gt; {
            alert(&quot;Mermaid code copied to clipboard!&quot;);
        }).catch(err =&gt; {
            console.error(&#39;Failed to copy: &#39;, err);
        });
    }
&lt;/script&gt;

&lt;h2&gt;1. Latest Guidelines for KML Files on PARIVESH Portal&lt;br&gt;&lt;small&gt;(PCCF Maharashtra Circular No. Desk-17/FCA-S1/NodalCell/25-26/1943 dated 20/11/2025)&lt;/small&gt;&lt;/h2&gt;

&lt;p&gt;Accurate KML preparation is now mandatory. Non-standard files are auto-rejected at scrutiny stage.&lt;/p&gt;

&lt;h3&gt;❌ Files NOT Supported&lt;/h3&gt;
&lt;ul&gt;
    &lt;li&gt;KML files larger than &lt;strong&gt;200 MB&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;Any &lt;strong&gt;KMZ&lt;/strong&gt; files&lt;/li&gt;
    &lt;li&gt;KML files with TBM images embedded in waypoints&lt;/li&gt;
    &lt;li&gt;Multi-geometry KML files with more than &lt;strong&gt;200 segments&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;🌲 Colour Codes (Mandatory)&lt;/h3&gt;
&lt;table&gt;
    &lt;tr&gt;&lt;th&gt;Forest Type&lt;/th&gt;&lt;th&gt;Colour&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Reserve Forest&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Green&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Protected Forest&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Yellow&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Zudpi Jungle&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Green&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Private Forest / Identified Forest&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Pink&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Non-forest area&lt;/td&gt;&lt;td&gt;&lt;strong&gt;No colour filling&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;h3&gt;✅ General Instructions (Must Follow)&lt;/h3&gt;
&lt;ol&gt;
    &lt;li&gt;Only the uploaded KML files of diverted forest area and Compensatory Afforestation (CA) land on PARIVESH will be used for scrutiny.&lt;/li&gt;
    &lt;li&gt;KML files submitted offline (CD/Map) &lt;strong&gt;must exactly match&lt;/strong&gt; the online uploaded files.&lt;/li&gt;
    &lt;li&gt;Use &lt;strong&gt;Polygons only&lt;/strong&gt; — Lines are not accepted for forest land depiction.&lt;/li&gt;
    &lt;li&gt;KML must display: Length, Width, Area, Compartment Number, Survey Number, Village name, Taluka name, Range, Division, and Legal status of forest land.&lt;/li&gt;
    &lt;li&gt;The area of the KML polygon &lt;strong&gt;must exactly match&lt;/strong&gt; the area shown in KML properties.&lt;/li&gt;
&lt;/ol&gt;
&lt;p class=&quot;note&quot;&gt;Tip from field: While preparing KML in Google Earth Pro, right-click the polygon → Properties → Description tab and manually enter all the above details. This saves huge time during DCF verification.&lt;/p&gt;

&lt;h2&gt;2. Simplified Procedure for Proposals up to 1 Hectare&lt;br&gt;&lt;small&gt;Under Scheduled Tribes &amp;amp; Other Traditional Forest Dwellers (Recognition of Forest Rights) Act, 2006 – Section 3(2)&lt;/small&gt;&lt;/h2&gt;

&lt;p&gt;Most PWD village-road, school, anganwadi, water supply and minor irrigation works fall under this category. Faster approval route through Gram Sabha + Range Forest Officer.&lt;/p&gt;

&lt;h3&gt;Checklist to be filled by User Agency (Sample-K)&lt;/h3&gt;
&lt;table&gt;
    &lt;tr&gt;&lt;th&gt;Sr.&lt;/th&gt;&lt;th&gt;Details&lt;/th&gt;&lt;th&gt;Compliance&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;7/12 Extract / Ferfar Utare of proposed land&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;Survey No. / Gat No. / Compartment No. mentioned?&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;Survey of India map (1 inch = 2 miles or 1:50,000) attached?&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;Justification for site selection mentioned?&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;No. of trees to be felled &amp;amp; retained (per hectare) mentioned?&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;Component-wise area statement of proposed work&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;Detailed map of proposed building / work&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;Proposal falls under any of 13 activities listed in Section 3(2)?&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;Proposal area ≤ 1 hectare?&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;Undertaking for double plantation &amp;amp; 5-year maintenance submitted?&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;Gram Sabha recommendation with 50% quorum?&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;Tahsildar certificate that non-forest land is not available?&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;h3&gt;Documents to be submitted (User Agency + Forest Department)&lt;/h3&gt;
&lt;ul&gt;
    &lt;li&gt;Sample-K (filled by User Agency)&lt;/li&gt;
    &lt;li&gt;Gram Sabha resolution + proceeding extract&lt;/li&gt;
    &lt;li&gt;1:50,000 scale map of proposed area&lt;/li&gt;
    &lt;li&gt;Detailed component-wise map of work&lt;/li&gt;
    &lt;li&gt;Administrative &amp;amp; Technical sanction letters&lt;/li&gt;
    &lt;li&gt;Sample-Kh (filled by Range Forest Officer) + Site Inspection + GPS Polygon&lt;/li&gt;
    &lt;li&gt;Certificate that no court case / FRA claims exist&lt;/li&gt;
    &lt;li&gt;7/12 extracts of proposed land &amp;amp; CA land&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Ready-to-use Certificates (Forest Officer side)&lt;/h3&gt;
&lt;ul&gt;
    &lt;li&gt;No court case / claim certificate&lt;/li&gt;
    &lt;li&gt;No tree felling certificate (if area &amp;lt;1 ha and zero trees)&lt;/li&gt;
    &lt;li&gt;Approved work requires exactly ___ ha forest land&lt;/li&gt;
    &lt;li&gt;Project will be completed within 1 year after permission&lt;/li&gt;
    &lt;li&gt;Tahsildar certificate for non-availability of non-forest land&lt;/li&gt;
    &lt;li&gt;Double plantation &amp;amp; maintenance undertaking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;3. Comprehensive Checklist for Regular FCA Proposals&lt;br&gt;&lt;small&gt;Under Van (Sanrakshan Evam Samvardhan) Adhiniyam, 1980&lt;/small&gt;&lt;/h2&gt;

&lt;p&gt;For projects larger than 1 ha or linear projects (roads, pipelines, transmission lines) — this is the master checklist used by DCF/CCF.&lt;/p&gt;

&lt;h3&gt;A. KML Files &amp;amp; Maps (must be verified &amp;amp; counter-signed by Surveyor + DCF + User Agency)&lt;/h3&gt;
&lt;ol&gt;
    &lt;li&gt;KML of proposed diversion area&lt;/li&gt;
    &lt;li&gt;KML of Compensatory Afforestation (CA) area&lt;/li&gt;
    &lt;li&gt;Geo-referenced digital map (shape file) using Total Station / DGPS showing forest / non-forest / adjoining land in different colours + Forest compartment boundary + Satellite imagery for density&lt;/li&gt;
    &lt;li&gt;Proposed forest &amp;amp; non-forest area on Topo-sheet&lt;/li&gt;
    &lt;li&gt;Map showing distance (in km) from nearest Protected Area / ESZ&lt;/li&gt;
    &lt;li&gt;Village map of proposed area&lt;/li&gt;
    &lt;li&gt;Map of alternative alignment / route examined&lt;/li&gt;
    &lt;li&gt;Map of CA land with geo-coordinates&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;B. Certificates by Deputy Conservator of Forests (DCF) — 17 Nos.&lt;/h3&gt;
&lt;ul&gt;
    &lt;li&gt;Documents verification certificate&lt;/li&gt;
    &lt;li&gt;Justification of site specificity&lt;/li&gt;
    &lt;li&gt;Certificate of absence of alternatives &amp;amp; minimum forest demand&lt;/li&gt;
    &lt;li&gt;Alternatives examined for linear projects&lt;/li&gt;
    &lt;li&gt;Wildlife certificate (not part of PA / Sanctuary)&lt;/li&gt;
    &lt;li&gt;Distance from Protected Area certificate&lt;/li&gt;
    &lt;li&gt;No impact on monuments / cultural / historical sites&lt;/li&gt;
    &lt;li&gt;No violation of FCA 1980 certificate&lt;/li&gt;
    &lt;li&gt;Non-forest area not covered under Maharashtra Private Forest Act 1975&lt;/li&gt;
    &lt;li&gt;List of Identified forests&lt;/li&gt;
    &lt;li&gt;Net Present Value (NPV) certificate with eco-class (GOI letter 05/02/2009)&lt;/li&gt;
    &lt;li&gt;Tree felling certificate&lt;/li&gt;
    &lt;li&gt;Species-wise / girth-wise tree list + estimate (counter-signed by DCF)&lt;/li&gt;
    &lt;li&gt;CA area identification &amp;amp; site suitability certificate&lt;/li&gt;
    &lt;li&gt;7/12 extract / RoR of proposed land &amp;amp; CA land&lt;/li&gt;
    &lt;li&gt;Compensatory Afforestation scheme (Model No. as per PCCF letter dated 19/11/2019)&lt;/li&gt;
    &lt;li&gt;Site Inspection Report of DCF&lt;/li&gt;
    &lt;li&gt;Part-II form duly filled&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;C. Certificates by Chief Conservator of Forests (CCF)&lt;/h3&gt;
&lt;ul&gt;
    &lt;li&gt;Site Inspection Report of CCF&lt;/li&gt;
    &lt;li&gt;NPV certificate counter-signed by CCF&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;D. Documents / Undertakings by Project Agency (User Agency) — 18 Nos.&lt;/h3&gt;
&lt;ul&gt;
    &lt;li&gt;Detailed Project Note with salient features&lt;/li&gt;
    &lt;li&gt;Justification of site specificity&lt;/li&gt;
    &lt;li&gt;Item-wise break-up of forest &amp;amp; non-forest area&lt;/li&gt;
    &lt;li&gt;Attempts made to locate non-forest land + reasons for rejection&lt;/li&gt;
    &lt;li&gt;Undertaking to pay NPV as per GoI orders&lt;/li&gt;
    &lt;li&gt;Undertaking to bear full cost of CA&lt;/li&gt;
    &lt;li&gt;Undertaking to bear tree felling &amp;amp; allied works cost&lt;/li&gt;
    &lt;li&gt;FRA Certificate&lt;/li&gt;
    &lt;li&gt;Undertaking of no violation of FCA 1980&lt;/li&gt;
    &lt;li&gt;Cost-Benefit Analysis&lt;/li&gt;
    &lt;li&gt;Undertaking to obtain Environmental Clearance (if applicable)&lt;/li&gt;
    &lt;li&gt;Non-indemnity undertaking to Forest Department&lt;/li&gt;
    &lt;li&gt;NOC from private owner (if Private Forest land involved)&lt;/li&gt;
    &lt;li&gt;Undertaking for Catchment Area Treatment Plan&lt;/li&gt;
    &lt;li&gt;Catchment Area Treatment Plan document&lt;/li&gt;
    &lt;li&gt;Muck Disposal Plan&lt;/li&gt;
    &lt;li&gt;Undertaking regarding location inside/outside Scheduled Tribal Area&lt;/li&gt;
    &lt;li&gt;No Objection Certificate from MD, FDCM (if required)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;new-section&quot;&gt;
&lt;h2&gt;4. Documents Required for Tree Ownership Certificate (Maliki Prakaran / झाडांची मालकी प्रमाणपत्र)&lt;br&gt;&lt;small&gt;Maharashtra Revenue Department – Essential List for Private / Identified Forest Land&lt;/small&gt;&lt;/h2&gt;

&lt;p&gt;Whenever your proposal involves &lt;strong&gt;Private Forest&lt;/strong&gt;, &lt;strong&gt;Identified Forest&lt;/strong&gt; or tree enumeration on non-government land, you &lt;strong&gt;must&lt;/strong&gt; attach the complete Tree Ownership (Maliki) documents. These are issued by Talathi → Tahsildar → District Collector and are cross-verified by the Forest Department.&lt;/p&gt;

&lt;p&gt;Without these, DCF will not accept tree felling estimates or CA calculations — a very common reason for rejection in PWD road &amp;amp; EPC projects.&lt;/p&gt;

&lt;h3&gt;Complete Checklist of 11 Documents (मालकी प्रकरणांसाठी आवश्यक असलेली कागदपत्रे)&lt;/h3&gt;
&lt;table&gt;
    &lt;tr&gt;&lt;th&gt;Sr.&lt;/th&gt;&lt;th&gt;Document&lt;/th&gt;&lt;th&gt;Issued By&lt;/th&gt;&lt;th&gt;Purpose&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;strong&gt;7/12 Extract&lt;/strong&gt; showing details of trees *&lt;/td&gt;&lt;td&gt;Talathi&lt;/td&gt;&lt;td&gt;Proof of land + tree ownership&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Consent letter / Jamband Patra&lt;/strong&gt; (if more than one occupant in 7/12) *&lt;/td&gt;&lt;td&gt;Other occupants + in presence of Tahsildar&lt;/td&gt;&lt;td&gt;Multiple owners case&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Gav Form No. 8&lt;/strong&gt; *&lt;/td&gt;&lt;td&gt;Talathi&lt;/td&gt;&lt;td&gt;Official village record&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Survey Maps&lt;/strong&gt; (Settlement / Re-measurement / Consolidation / Present status / TILR) *&lt;/td&gt;&lt;td&gt;Talathi / Tahsildar&lt;/td&gt;&lt;td&gt;Exact boundary &amp;amp; survey number proof&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Boundary Certificate&lt;/strong&gt; showing names of adjacent land owners &amp;amp; survey numbers *&lt;/td&gt;&lt;td&gt;Talathi&lt;/td&gt;&lt;td&gt;Neighbouring ownership details&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Ownership Certificate&lt;/strong&gt; for land &amp;amp; trees (Class-I / Class-II Bhogwatidar) *&lt;/td&gt;&lt;td&gt;Tahsildar / Naib Tahsildar / SDO&lt;/td&gt;&lt;td&gt;Clear legal ownership of land &amp;amp; trees&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Caste Certificate&lt;/strong&gt; (if applicant belongs to Scheduled Tribe)&lt;/td&gt;&lt;td&gt;Tahsildar / SDO (Revenue)&lt;/td&gt;&lt;td&gt;ST category cases&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Survey-number-wise Tree List&lt;/strong&gt; *&lt;/td&gt;&lt;td&gt;Applicant / Talathi&lt;/td&gt;&lt;td&gt;Exact tree enumeration&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Certificate for water source&lt;/strong&gt; (if bank, tank or water body within 30 m)&lt;/td&gt;&lt;td&gt;District Collector&lt;/td&gt;&lt;td&gt;Restriction near water bodies&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Certificate for low tree growth&lt;/strong&gt; (if non-agricultural land with sparse trees – 20 trees = 1 new plantation)&lt;/td&gt;&lt;td&gt;District Collector&lt;/td&gt;&lt;td&gt;Compensatory plantation relaxation&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Written Certificate from Forest Officer&lt;/strong&gt; *&lt;/td&gt;&lt;td&gt;Range Forest Officer / DCF&lt;/td&gt;&lt;td&gt;Final Forest Department confirmation&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;p class=&quot;note&quot;&gt;* = Most critical documents (starred in official circular). Keep scanned copies ready with counter-signatures.&lt;/p&gt;

&lt;h3&gt;Practical Tips for PWD Engineers&lt;/h3&gt;
&lt;ul&gt;
    &lt;li&gt;Start with Talathi for 7/12 + Gav Form 8 + Boundary Certificate — these three are needed in almost every proposal.&lt;/li&gt;
    &lt;li&gt;If survey number touches government land, get TILR map + Tahsildar certified map immediately.&lt;/li&gt;
    &lt;li&gt;Tree list (Sr. 8) must match the enumeration done by Forest Department — mismatch = rejection.&lt;/li&gt;
    &lt;li&gt;For road projects, attach chainage-wise tree list in the Maliki file itself.&lt;/li&gt;
    &lt;li&gt;Coordinate with Tahsildar early — the entire Maliki file usually takes 15–30 days.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;h2&gt;Practical Tips from a PWD Engineer’s Desk (Updated with Maliki Documents)&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;Always prepare two separate KMLs — one for diversion and one for CA land. Name them clearly: &lt;code&gt;ProjectName_Diversion.kml&lt;/code&gt; and &lt;code&gt;ProjectName_CA.kml&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;Use QGIS or Google Earth Pro with Survey of India toposheet as base. Export as KML only after adding all attributes.&lt;/li&gt;
    &lt;li&gt;For road projects, show chainage on the KML polygon description &lt;strong&gt;and&lt;/strong&gt; in the Maliki tree list.&lt;/li&gt;
    &lt;li&gt;Keep scanned copies of all counter-signatures + complete Maliki file ready — PARIVESH now asks for geo-tagged photos also in many cases.&lt;/li&gt;
    &lt;li&gt;Coordinate with Range Forest Officer early — his GPS polygon, Part-II form &lt;strong&gt;and&lt;/strong&gt; Maliki verification are the backbone of the proposal.&lt;/li&gt;
    &lt;li&gt;NPV, CA scheme model number, tree enumeration and &lt;strong&gt;Maliki documents&lt;/strong&gt; are the four most common reasons for delay — get them vetted by DCF before final submission.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;वन जमीन वापरासाठी - तपासणी सूची व प्रमाणपत्रे (HTML आवृत्ती)&lt;/h1&gt;
&lt;div class=&quot;container&quot;&gt;

    &lt;!-- Checklist Table 1 --&gt;
    &lt;div class=&quot;checklist&quot;&gt;
        &lt;div class=&quot;section-title&quot;&gt;१. तपासणाऱ्या सूची (वापरकर्ता अभिकरणाने नमुना-क सोबत जोडणे)&lt;/div&gt;
        &lt;table&gt;
            &lt;thead&gt;
                &lt;tr&gt;
                    &lt;th style=&quot;width:50px;&quot;&gt;अ.क्र.&lt;/th&gt;
                    &lt;th&gt;तपशिल&lt;/th&gt;
                    &lt;th class=&quot;yes-no&quot;&gt;होय&lt;/th&gt;
                    &lt;th class=&quot;yes-no&quot;&gt;नाही&lt;/th&gt;
                    &lt;th class=&quot;remark&quot;&gt;शेरा&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr&gt;&lt;td&gt;२&lt;/td&gt;&lt;td&gt;प्रस्तावित जमिनीचा ७/१२ उतारा / फेरफार उतारा&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;३&lt;/td&gt;&lt;td&gt;सर्वे क्रमांक / गट क्रमांक / कक्ष क्रमांक नमूद आहे काय?&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;३&lt;/td&gt;&lt;td&gt;रु.५,००,००० व इंच = २ मैल प्रमाणे नकाशा जोडला आहे (सर्वे ऑफ इंडियाचा नकाशा)&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;४&lt;/td&gt;&lt;td&gt;प्रस्तावाच्या स्थळाबाबत समर्थन नमूद केले आहे काय?&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;५&lt;/td&gt;&lt;td&gt;प्रस्तावातर्गत तोडावयाच्या झाडांची संख्या व राखून ठेवावयाच्या झाडांची संख्या (प्रति हेक्टरी) नमूद केली आहे काय?&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;६&lt;/td&gt;&lt;td&gt;प्रस्तावित कामाचे क्षेत्रासंबंधी वनविभागीय क्षेत्र विवरण&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;७&lt;/td&gt;&lt;td&gt;प्रस्तावित इमारत / कामाचा नकाशा&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;८&lt;/td&gt;&lt;td&gt;मागणी केलेल्या प्रस्ताव उक्त अधिनियमातील कलम ३(२) मध्ये नमूद केलेल्या १३ बाबींपैकी आहे काय?&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;९&lt;/td&gt;&lt;td&gt;मागणी केलेल्या प्रस्ताव १ हेक्टरच्या मर्यादित आहे काय?&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;१०&lt;/td&gt;&lt;td&gt;तोड होणा-या झाडांच्या बदल्यात दुप्पट झाडे लावून देण्याबाबत व देखभालीबाबत हमीपत्र दिले आहे काय?&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;११&lt;/td&gt;&lt;td&gt;ग्रामसभेचे (५०%) गणपूर्ती शिफारस केली आहे काय?&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;१२&lt;/td&gt;&lt;td&gt;वनंतर जमीन उपलब्ध नसल्याबाबतचा तहसिलदार यांचा दाखला जोडलेला आहे काय?&lt;/td&gt;&lt;td style=&quot;text-align:center;&quot;&gt;होय&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
        &lt;div style=&quot;display:flex; justify-content:space-between; margin-top:20px; font-size:14px;&quot;&gt;
            &lt;div&gt;&lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;/div&gt;
            &lt;div&gt;&lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________&lt;/div&gt;
            &lt;div&gt;&lt;strong&gt;कार्यकारी यंत्रणा&lt;/strong&gt;&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- Checklist Table 2 --&gt;
    &lt;div class=&quot;checklist&quot;&gt;
        &lt;div class=&quot;section-title&quot;&gt;२. अनुसूचीत जमाती व इतर पारंपारिक वननिवासी (वन हक्काची मान्यता) अधिनियम-२००६ च्या कलम ३ चे पोटकलम (२) अन्वये दस्तऐवज सूची&lt;/div&gt;
        &lt;table&gt;
            &lt;thead&gt;
                &lt;tr&gt;
                    &lt;th style=&quot;width:50px;&quot;&gt;अ.क्र.&lt;/th&gt;
                    &lt;th&gt;तपशिल&lt;/th&gt;
                    &lt;th style=&quot;width:120px;&quot;&gt;पान क्रमांक&lt;/th&gt;
                    &lt;th style=&quot;width:80px;&quot;&gt;पासून&lt;/th&gt;
                    &lt;th style=&quot;width:80px;&quot;&gt;पर्यंत&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody&gt;
                &lt;tr&gt;&lt;td colspan=&quot;5&quot; style=&quot;background:#f0f0f0; font-weight:700;&quot;&gt;वापरकर्ता अभिकरणाने सादर करावयाचे दस्तऐवज&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;१&lt;/td&gt;&lt;td&gt;वापरकर्ता अभिकरणाने सादर करावयाचे दस्तऐवज&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;२&lt;/td&gt;&lt;td&gt;वापरकर्ता अभिकरणाने भरलेला नमुना-क&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;३&lt;/td&gt;&lt;td&gt;ग्रामसभा ठराव&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;४&lt;/td&gt;&lt;td&gt;ग्रामसभा प्रासिडिंगचा उतारा&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;५&lt;/td&gt;&lt;td&gt;प्रस्तावांतर्गत क्षेत्राचा नकाशा (१:५००००)&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;६&lt;/td&gt;&lt;td&gt;प्रस्तावित कामाचा सविस्तर हेतुनिहाय विवरण नकाशा&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;७&lt;/td&gt;&lt;td&gt;कामाचे अंदाजपत्रक&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;८&lt;/td&gt;&lt;td&gt;प्रशासकीय मंजुरीचे पत्र व तांत्रिक मंजुरी पत्र&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;९&lt;/td&gt;&lt;td&gt;ग्रामसभेमध्ये ५०% गणपूर्तता बाबतचा दाखला&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;१०&lt;/td&gt;&lt;td&gt;सदर प्रयोजनासाठी वनेतर जमीन उपलब्ध नसल्याबाबतचा तहसिलदार यांचा दाखला&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                
                &lt;tr&gt;&lt;td colspan=&quot;5&quot; style=&quot;background:#f0f0f0; font-weight:700;&quot;&gt;वनक्षेत्रपाल यांनी सादर करावयाचे दस्तऐवज&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;११&lt;/td&gt;&lt;td&gt;वनक्षेत्रपाल यांनी भरलेला नमुना-ख (स्वयंस्पष्ट अभिप्रायसह)&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;१२&lt;/td&gt;&lt;td&gt;स्थळावरचा पंचनामा व जी.पी.एस. पॉलिगॉन नकाशा जोडलेला आहे.&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;१३&lt;/td&gt;&lt;td&gt;स्थळनिरीक्षण पंचनामा&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;१४&lt;/td&gt;&lt;td&gt;कोर्टकेस / इतर दावा आहे किंवा नाही याबाबत प्रमाणपत्र&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;१५&lt;/td&gt;&lt;td&gt;प्रस्तावित वनहक्क २००६ चे वैयक्तिक व सामुहिक दावे नसले बाबतचे प्रमाणपत्र&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
            &lt;/tbody&gt;
        &lt;/table&gt;
        &lt;div style=&quot;display:flex; justify-content:space-between; margin-top:20px; font-size:14px;&quot;&gt;
            &lt;div&gt;&lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;/div&gt;
            &lt;div&gt;&lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________&lt;/div&gt;
            &lt;div&gt;&lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;h2 style=&quot;margin-top:60px;&quot;&gt;प्रमाणपत्रे (प्रत्येक प्रमाणपत्र वेगळ्या पानावर)&lt;/h2&gt;

    &lt;!-- Certificate 1 --&gt;
    &lt;div class=&quot;certificate-page&quot;&gt;
        &lt;div class=&quot;certificate-content&quot;&gt;
            &lt;div class=&quot;certificate-header&quot;&gt;प्रमाणपत्र&lt;/div&gt;
            &lt;div class=&quot;certificate-title&quot;&gt;प्रमाणित करण्यात येते की, वापरकर्ता अभिकरणाने सादर केलेला प्रस्ताव उक्त अधिनियमातील कलम ३(२) मध्ये नमूद केलेल्या १३ पैकी आहे. वापरकर्ता अभिकरणाने मागणी केलेल्या ________________ क्षेत्रावर कोर्टकेस / इतर दावा दाखल नाही. प्रस्ताव योग्य असल्याने मंजुरीबाबत शिफारस करणेत येत आहे.&lt;/div&gt;
            &lt;div class=&quot;signature-block&quot;&gt;
                &lt;div class=&quot;signature-left&quot;&gt;
                    &lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;br&gt;
                    &lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________
                &lt;/div&gt;
                &lt;div class=&quot;signature-right&quot;&gt;
                    &lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;page-number&quot;&gt;पान १&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- Certificate 2 --&gt;
    &lt;div class=&quot;certificate-page&quot;&gt;
        &lt;div class=&quot;certificate-content&quot;&gt;
            &lt;div class=&quot;certificate-header&quot;&gt;प्रमाणपत्र&lt;/div&gt;
            &lt;div class=&quot;certificate-title&quot;&gt;प्रमाणित करण्यात येते की, वापरकर्ता अभिकरणाने सादर केलेला प्रस्ताव उक्त अधिनियमातील कलम ३(२) मध्ये नमूद केलेल्या १३ पैकी आहे. वापरकर्ता अभिकरणाने मागणी केलेल्या मौजे ________________ हेक्टर क्षेत्राची प्रकल्प यंत्रणेचे प्रतिनिधी समवेत दिनांक ________________ रोजी स्थळ पाहणी केली असून मागणी केलेले क्षेत्र १.०० हेक्टरपेक्षा कमी असून कक्ष क्र. ________________ क्षेत्रात कोणतीही झाडे नसून एकाही झाडाची तोड होणार नाही. नियमानुसार प्रस्ताव योग्य असल्याने मंजुरीबाबत शिफारस करणेत येत आहे.&lt;/div&gt;
            &lt;div class=&quot;signature-block&quot;&gt;
                &lt;div class=&quot;signature-left&quot;&gt;
                    &lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;br&gt;
                    &lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________
                &lt;/div&gt;
                &lt;div class=&quot;signature-right&quot;&gt;
                    &lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;page-number&quot;&gt;पान २&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- Certificate 3 --&gt;
    &lt;div class=&quot;certificate-page&quot;&gt;
        &lt;div class=&quot;certificate-content&quot;&gt;
            &lt;div class=&quot;certificate-header&quot;&gt;प्रमाणपत्र&lt;/div&gt;
            &lt;div class=&quot;certificate-title&quot;&gt;प्रमाणित करण्यात येते की, मंजूर असलेली ________________ कामासाठी ________________ हेक्टर वनजमिनीची आवश्यकता आहे.&lt;/div&gt;
            &lt;div class=&quot;signature-block&quot;&gt;
                &lt;div class=&quot;signature-left&quot;&gt;
                    &lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;br&gt;
                    &lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________
                &lt;/div&gt;
                &lt;div class=&quot;signature-right&quot;&gt;
                    &lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;&lt;br&gt;
                    &lt;strong&gt;संबंधित यंत्रणा&lt;/strong&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;page-number&quot;&gt;पान ३&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- Certificate 4 --&gt;
    &lt;div class=&quot;certificate-page&quot;&gt;
        &lt;div class=&quot;certificate-content&quot;&gt;
            &lt;div class=&quot;certificate-header&quot;&gt;प्रमाणपत्र&lt;/div&gt;
            &lt;div class=&quot;certificate-title&quot;&gt;प्रमाणित करण्यात येते की, मंजूर असलेली ________________ कामासाठी ________________ हेक्टर मध्ये काम वगळता योजनेचे काम प्रगतीत आहे.&lt;/div&gt;
            &lt;div class=&quot;signature-block&quot;&gt;
                &lt;div class=&quot;signature-left&quot;&gt;
                    &lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;br&gt;
                    &lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________
                &lt;/div&gt;
                &lt;div class=&quot;signature-right&quot;&gt;
                    &lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;&lt;br&gt;
                    &lt;strong&gt;संबंधित यंत्रणा&lt;/strong&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;page-number&quot;&gt;पान ४&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- Certificate 5 --&gt;
    &lt;div class=&quot;certificate-page&quot;&gt;
        &lt;div class=&quot;certificate-content&quot;&gt;
            &lt;div class=&quot;certificate-header&quot;&gt;प्रमाणपत्र&lt;/div&gt;
            &lt;div class=&quot;certificate-title&quot;&gt;प्रमाणित करण्यात येते की, मंजूर असलेली ________________ कामासाठी ________________ हेक्टर हे काम वनखात्याची परवानगी मिळाल्यानंतर १ वर्षाच्या आत काम पूर्ण करण्यात येईल.&lt;/div&gt;
            &lt;div class=&quot;signature-block&quot;&gt;
                &lt;div class=&quot;signature-left&quot;&gt;
                    &lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;br&gt;
                    &lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________
                &lt;/div&gt;
                &lt;div class=&quot;signature-right&quot;&gt;
                    &lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;&lt;br&gt;
                    &lt;strong&gt;संबंधित यंत्रणा&lt;/strong&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;page-number&quot;&gt;पान ५&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- Certificate 6 --&gt;
    &lt;div class=&quot;certificate-page&quot;&gt;
        &lt;div class=&quot;certificate-content&quot;&gt;
            &lt;div class=&quot;certificate-header&quot;&gt;प्रमाणपत्र&lt;/div&gt;
            &lt;div class=&quot;certificate-title&quot;&gt;प्रमाणित करण्यात येते की, मंजूर असलेली ________________ या कामासाठी मागणी करण्यात आलेल्या जमिनी व्यतिरिक्त खाजगी / सरकारी / वनेतर जमीन उपलब्ध नाही. तसा तहसिलदार ________________ यांचा दाखला सोबत जोडण्यात आलेला आहे.&lt;/div&gt;
            &lt;div class=&quot;signature-block&quot;&gt;
                &lt;div class=&quot;signature-left&quot;&gt;
                    &lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;br&gt;
                    &lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________
                &lt;/div&gt;
                &lt;div class=&quot;signature-right&quot;&gt;
                    &lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;&lt;br&gt;
                    &lt;strong&gt;संबंधित यंत्रणा&lt;/strong&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;page-number&quot;&gt;पान ६&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- Certificate 7 --&gt;
    &lt;div class=&quot;certificate-page&quot;&gt;
        &lt;div class=&quot;certificate-content&quot;&gt;
            &lt;div class=&quot;certificate-header&quot;&gt;प्रमाणपत्र&lt;/div&gt;
            &lt;div class=&quot;certificate-title&quot;&gt;प्रमाणित करण्यात येते की, मंजूर असलेली ________________ या कामासाठी हे काम पूर्ण करण्यात आल्यानंतर योजनेच्या क्षेत्रात बाजूस झाडे लावून त्यांचे संगोपन करण्यात येईल.&lt;/div&gt;
            &lt;div class=&quot;signature-block&quot;&gt;
                &lt;div class=&quot;signature-left&quot;&gt;
                    &lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;br&gt;
                    &lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________
                &lt;/div&gt;
                &lt;div class=&quot;signature-right&quot;&gt;
                    &lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;&lt;br&gt;
                    &lt;strong&gt;संबंधित यंत्रणा&lt;/strong&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;page-number&quot;&gt;पान ७&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- Certificate 8 --&gt;
    &lt;div class=&quot;certificate-page&quot;&gt;
        &lt;div class=&quot;certificate-content&quot;&gt;
            &lt;div class=&quot;certificate-header&quot;&gt;प्रमाणपत्र&lt;/div&gt;
            &lt;div class=&quot;certificate-title&quot;&gt;प्रमाणित करण्यात येते की, मंजूर असलेली ________________ या कामासाठी मागणी करण्यात आलेल्या जमिनी व्यतिरिक्त खाजगी / सरकारी / वनेतर जमीन उपलब्ध नाही. तसा तहसिलदार ________________ यांचा दाखला सोबत जोडण्यात आलेला आहे.&lt;/div&gt;
            &lt;div class=&quot;signature-block&quot;&gt;
                &lt;div class=&quot;signature-left&quot;&gt;
                    &lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;br&gt;
                    &lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________
                &lt;/div&gt;
                &lt;div class=&quot;signature-right&quot;&gt;
                    &lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;page-number&quot;&gt;पान ८&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- Certificate 9 --&gt;
    &lt;div class=&quot;certificate-page&quot;&gt;
        &lt;div class=&quot;certificate-content&quot;&gt;
            &lt;div class=&quot;certificate-header&quot;&gt;प्रमाणपत्र&lt;/div&gt;
            &lt;div class=&quot;certificate-title&quot;&gt;प्रमाणित करण्यात येते की, मंजूर असलेली ________________ या कामासाठी हे काम पूर्ण करण्यात आल्यानंतर योजनेच्या क्षेत्रात बाजूस झाडे लावून त्यांचे संगोपन करण्यात येईल.&lt;/div&gt;
            &lt;div class=&quot;signature-block&quot;&gt;
                &lt;div class=&quot;signature-left&quot;&gt;
                    &lt;strong&gt;दिनांक :&lt;/strong&gt; ___________________&lt;br&gt;
                    &lt;strong&gt;ठिकाण :&lt;/strong&gt; ___________________
                &lt;/div&gt;
                &lt;div class=&quot;signature-right&quot;&gt;
                    &lt;strong&gt;वनपरिक्षेत्र अधिकारी&lt;/strong&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;page-number&quot;&gt;पान ९&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;
    console.log(&quot;%c✅ वन जमीन तपासणी सूची व प्रमाणपत्रे HTML तयार आहे! मुद्रित करण्यासाठी Ctrl + P दाबा. प्रत्येक प्रमाणपत्र स्वतंत्र पानावर येईल.&quot;, &quot;color:#006400; font-size:14px; font-weight:bold&quot;);
&lt;/script&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Forest clearance is no longer just paperwork — it is a technical deliverable that can make or break your project timeline. Follow the above KML guidelines, use the correct checklist as per area (≤1 ha or &amp;gt;1 ha), attach complete Tree Maliki documents, and ensure every map and certificate is counter-signed.&lt;/p&gt;

&lt;p class=&quot;highlight&quot;&gt;Save this article. Bookmark the PCCF circular dated 20/11/2025 and the Maliki document list. Next time you prepare a forest diversion proposal for any PWD or EPC project in Maharashtra, you will finish the documentation in half the time and with zero rejection risk.&lt;/p&gt;
&lt;hr&gt;
&lt;p style=&quot;font-size:0.9em; text-align:center; color:#555;&quot;&gt;
    Last updated: April 2026 | Source: Official PCCF Maharashtra Circulars, Van Sanrakshan Adhiniyam 1980 checklists &amp;amp; Revenue Department Maliki Guidelines
&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/04/maharashtra-forest-land-diversion-2026.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-776033809780190442</guid><pubDate>Sat, 11 Apr 2026 05:17:00 +0000</pubDate><atom:updated>2026-06-23T14:06:57.774+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><title>rules and guidelines for granting permission for access roads (approach roads) to fuel stations, resorts, hotels, and other establishments located along State Highways and District Roads</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;PWD Access Road Norms Calculator&lt;/title&gt;
    &lt;style&gt;
        body { font-family: &#39;Segoe UI&#39;, Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f7f6; margin: 20px; color: #333; }
        .container { max-width: 600px; background: white; padding: 25px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); margin: auto; }
        h2 { color: #2c3e50; text-align: center; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
        .form-group { margin-bottom: 15px; }
        label { display: block; font-weight: bold; margin-bottom: 5px; }
        select, input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; box-sizing: border-box; }
        button { width: 100%; padding: 12px; background-color: #3498db; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; font-weight: bold; }
        button:hover { background-color: #2980b9; }
        .results { margin-top: 20px; display: none; }
        .result-item { padding: 10px; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; }
        .result-item:last-child { border-bottom: none; }
        .val { font-weight: bold; color: #e67e22; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;container&quot;&gt;
    &lt;h2&gt;Access Road Norms Checker&lt;/h2&gt;
    &lt;p style=&quot;font-size: 0.9em; color: #666; text-align: center;&quot;&gt;Based on PWD Maharashtra Circular Oct-2021&lt;/p&gt;
    
    &lt;div class=&quot;form-group&quot;&gt;
        &lt;label&gt;Area Type&lt;/label&gt;
        &lt;select id=&quot;areaType&quot;&gt;
            &lt;option value=&quot;rural&quot;&gt;Rural (Non-Urban)&lt;/option&gt;
            &lt;option value=&quot;urban&quot;&gt;Urban (Pop &gt; 20,000)&lt;/option&gt;
        &lt;/select&gt;
    &lt;/div&gt;

    &lt;div class=&quot;form-group&quot;&gt;
        &lt;label&gt;Intersecting Road Type&lt;/label&gt;
        &lt;select id=&quot;roadType&quot;&gt;
            &lt;option value=&quot;major&quot;&gt;NH / SH / MDR&lt;/option&gt;
            &lt;option value=&quot;minor&quot;&gt;ODR / VR / Local&lt;/option&gt;
        &lt;/select&gt;
    &lt;/div&gt;

    &lt;button onclick=&quot;calculateNorms()&quot;&gt;Check Norms&lt;/button&gt;

    &lt;div id=&quot;results&quot; class=&quot;results&quot;&gt;
        &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Min. Distance from Intersection:&lt;/span&gt; &lt;span class=&quot;val&quot; id=&quot;distIntersection&quot;&gt;-&lt;/span&gt;&lt;/div&gt;
        &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Min. Distance from Bridge/Culvert:&lt;/span&gt; &lt;span class=&quot;val&quot;&gt;100 m&lt;/span&gt;&lt;/div&gt;
        &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Min. Distance from Railway Level Crossing:&lt;/span&gt; &lt;span class=&quot;val&quot;&gt;100 m&lt;/span&gt;&lt;/div&gt;
        &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Min. Distance from Toll Plaza:&lt;/span&gt; &lt;span class=&quot;val&quot;&gt;1000 m&lt;/span&gt;&lt;/div&gt;
        &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Entry/Exit Radius (Min):&lt;/span&gt; &lt;span class=&quot;val&quot;&gt;15 m&lt;/span&gt;&lt;/div&gt;
        &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Buffer Strip Length (Min):&lt;/span&gt; &lt;span class=&quot;val&quot;&gt;12 m&lt;/span&gt;&lt;/div&gt;
        &lt;div class=&quot;result-item&quot;&gt;&lt;span&gt;Max Gradient of Access Road:&lt;/span&gt; &lt;span class=&quot;val&quot;&gt;2%&lt;/span&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;script&gt;
function calculateNorms() {
    const area = document.getElementById(&#39;areaType&#39;).value;
    const road = document.getElementById(&#39;roadType&#39;).value;
    let intersectionDist = &quot;&quot;;

    if (area === &quot;rural&quot;) {
        intersectionDist = (road === &quot;major&quot;) ? &quot;300 meters&quot; : &quot;100 meters&quot;;
    } else {
        intersectionDist = (road === &quot;major&quot;) ? &quot;100 meters&quot; : &quot;50 meters&quot;;
    }

    document.getElementById(&#39;distIntersection&#39;).innerText = intersectionDist;
    document.getElementById(&#39;results&#39;).style.display = &quot;block&quot;;
}
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;
&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/04/rules-and-guidelines-for-granting.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-1421818680713229609</guid><pubDate>Thu, 09 Apr 2026 06:49:00 +0000</pubDate><atom:updated>2026-06-23T14:07:21.198+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><category domain="http://www.blogger.com/atom/ns#">Software</category><title>comments</title><description>&lt;style&gt;
        body {
            font-family: &#39;Segoe UI&#39;, Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: #2d3748;
            max-width: 900px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f7fafc;
        }
        header {
            background-color: #28a745;
            color: white;
            padding: 24px;
            border-radius: 8px;
            margin-bottom: 30px;
            text-align: center;
            box-shadow: 0 4px 6px rgba(40, 167, 69, 0.15);
        }
        h1 { margin: 0; font-size: 26px; font-weight: 600; }
        h2 { color: #218838; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; margin-top: 35px; }
        h3 { color: #4a5568; margin-top: 20px; }
        code {
            background-color: #edf2f7;
            padding: 2px 6px;
            border-radius: 4px;
            font-family: Menlo, Monaco, Consolas, monospace;
            font-size: 0.9em;
            color: #c53030;
        }
        .info-box {
            background-color: #e6fffa;
            border-left: 4px solid #319795;
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 8px 8px 0;
        }
        .warning-box {
            background-color: #fff3cd;
            border-left: 4px solid #dd6b20;
            color: #856404;
            padding: 15px;
            margin: 20px 0;
            border-radius: 0 8px 8px 0;
        }
        .btn-preview {
            display: inline-block;
            background-color: #28a745;
            color: white;
            padding: 10px 20px;
            text-decoration: none;
            border-radius: 6px;
            font-weight: bold;
            font-size: 14px;
            margin: 10px 0;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
            background: white;
            box-shadow: 0 1px 3px rgba(0,0,0,0.05);
        }
        th, td {
            border: 1px solid #e2e8f0;
            padding: 12px;
            text-align: left;
        }
        th { background-color: #edf2f7; color: #4a5568; font-weight: 600; }
        ul, ol { padding-left: 22px; }
        li { margin-bottom: 8px; }
    &lt;/style&gt;
&lt;div style=&quot;text-align: center; font-family: &#39;Segoe UI&#39;, Arial, sans-serif; padding: 25px; border: 1px solid #ddd; border-radius: 12px; background: #ffffff; max-width: 500px; margin: 20px auto; box-shadow: 0 4px 10px rgba(0,0,0,0.05);&quot;&gt;
  
  &lt;h2 style=&quot;color: #28a745; margin-bottom: 10px;&quot;&gt;Project Management Tool&lt;/h2&gt;
  
  &lt;div style=&quot;background-color: #fff3cd; color: #856404; padding: 10px; border-radius: 5px; font-size: 13px; margin-bottom: 20px; text-align: left;&quot;&gt;
    &lt;strong&gt;Mobile User Tip:&lt;/strong&gt; If you have multiple Gmail accounts logged in, &lt;b&gt;Long-Press&lt;/b&gt; the button below and select &lt;b&gt;&quot;Open in Incognito/Private Tab&quot;&lt;/b&gt; to avoid errors.
  &lt;/div&gt;

  &lt;a href=&quot;https://script.google.com/macros/s/AKfycbxdSd390egkp3lWGYdBNblMkKM3RvNUKdt-lXR6pV3lxR89wlpjq1JL83bq1bO63xcB/exec&quot; 
     target=&quot;_blank&quot; 
     style=&quot;display: inline-block; background-color: #28a745; color: white; padding: 16px 30px; text-decoration: none; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 6px rgba(40, 167, 69, 0.3);&quot;&gt;
     Launch Form Now
  &lt;/a&gt;
&lt;/div&gt;

&lt;header&gt;
    &lt;h1&gt;User Guide: Project Management Tool Launcher&lt;/h1&gt;
    &lt;p&gt;Quick start instructions for accessing your web-based management form safely and avoiding account conflicts&lt;/p&gt;
&lt;/header&gt;

&lt;section&gt;
    &lt;h2&gt;1. Overview&lt;/h2&gt;
    &lt;p&gt;This deployment portal serves as the unified entry point for your web-based &lt;strong&gt;Project Management Tool&lt;/strong&gt;. The interface utilizes a micro-portal widget containing an integrated, secure redirection link linked to a production Google Apps Script backend engine deployment (&lt;code&gt;/exec&lt;/code&gt; endpoint).&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;2. Primary Access Action&lt;/h2&gt;
    &lt;p&gt;To enter your workspace dashboard environment, utilize the primary action control element located on your gateway portal card:&lt;/p&gt;
    
    &lt;div style=&quot;text-align: center; margin: 15px 0;&quot;&gt;
        &lt;span class=&quot;btn-preview&quot;&gt;Launch Form Now&lt;/span&gt;
    &lt;/div&gt;
    
    &lt;p&gt;Clicking or tapping this direct link initiates a secure browser frame routing payload out to the live script compiler hosting your functional input fields, sheets data processing macros, and reporting tools.&lt;/p&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;3. Critical Mobile Configuration &amp; Account Routing&lt;/h2&gt;
    &lt;p&gt;Because the macro backend framework relies on standard Google workspace ecosystems, multi-account login conditions on single client devices can cause session routing conflicts.&lt;/p&gt;
    
    &lt;div class=&quot;warning-box&quot;&gt;
        &lt;strong&gt;Mobile User Tip (Multi-Account Handling):&lt;/strong&gt;&lt;br&gt; 
        If you maintain multiple logged-in Google/Gmail accounts on a single mobile device, clicking the button directly may trigger a &lt;code&gt;403 / Authorization Error&lt;/code&gt; page. To circumvent this behavior:
        &lt;ol&gt;
            &lt;li&gt;&lt;strong&gt;Long-Press&lt;/strong&gt; (press and hold) the &lt;strong&gt;&quot;Launch Form Now&quot;&lt;/strong&gt; button component.&lt;/li&gt;
            &lt;li&gt;Select &lt;strong&gt;&quot;Open in Incognito Tab&quot;&lt;/strong&gt; or &lt;strong&gt;&quot;Open in Private Window&quot;&lt;/strong&gt; from the pop-up context menu.&lt;/li&gt;
            &lt;li&gt;Log in using the explicit credential profile assigned to your organizational project database.&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;4. Deployment Specifics&lt;/h2&gt;
    &lt;table&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th&gt;System Variable&lt;/th&gt;
                &lt;th&gt;Target Reference Value / Parameter&lt;/th&gt;
                &lt;th&gt;Purpose&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Deployment Link&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;https://script.google.com/macros/s/.../exec&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Active web app deployment address executing structural interface components.&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Environment Target&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;&lt;code&gt;_blank&lt;/code&gt;&lt;/td&gt;
                &lt;td&gt;Forces target window rendering out to secondary workspace tabs to preserve the state of your origin portal.&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;strong&gt;Conflict Resolution&lt;/strong&gt;&lt;/td&gt;
                &lt;td&gt;Incognito Routing / Account Isolator&lt;/td&gt;
                &lt;td&gt;Prevents active cookie state cross-contamination from blocking script execution layers.&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;/section&gt;

&lt;section&gt;
    &lt;h2&gt;5. Operational Support Guidelines&lt;/h2&gt;
    &lt;div class=&quot;info-box&quot;&gt;
        &lt;strong&gt;Troubleshooting Quick Checks:&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;Infinite Loading Loops:&lt;/strong&gt; Ensure your network firewall settings allow persistent scripts out to Google API development servers.&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Blank White Screens:&lt;/strong&gt; This typically indicates that cookies are blocked across sites. Switching the browser framework to private browsing modes immediately clears cached storage blocks.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;
&lt;/section&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/04/comments.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-716781961750643453</guid><pubDate>Sat, 04 Apr 2026 09:08:00 +0000</pubDate><atom:updated>2026-06-28T09:23:45.890+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><category domain="http://www.blogger.com/atom/ns#">Software</category><title>Land acquisition data entry</title><description>&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
    mermaid.initialize({
        startOnLoad: false,
        theme: &#39;default&#39;,
        flowchart: { useMaxWidth: true, htmlLabels: true, curve: &#39;basis&#39; }
    });
&lt;/script&gt;
&lt;script&gt;mermaid.initialize({ startOnLoad: false, theme: &#39;forest&#39; });&lt;/script&gt;

&lt;div id=&quot;land-acquisition-app&quot;&gt;
    &lt;style&gt;
        /* Scoped CSS for Blogger */
        #land-acquisition-app {
            font-family: &#39;Segoe UI&#39;, Tahoma, Geneva, Verdana, sans-serif;
            color: #333;
            max-width: 1000px;
            margin: 20px auto;
            line-height: 1.6;
        }
        #land-acquisition-app .card {
            background: #ffffff;
            border: 1px solid #e0e0e0;
            padding: 20px;
            margin-bottom: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.05);
        }
        #land-acquisition-app .grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 15px;
        }
        #land-acquisition-app input, #land-acquisition-app select {
            width: 100%;
            padding: 8px;
            margin: 5px 0;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
        #land-acquisition-app button {
            background-color: #34495e;
            color: white;
            border: none;
            padding: 10px 15px;
            border-radius: 4px;
            cursor: pointer;
            font-weight: bold;
            transition: 0.3s;
        }
        #land-acquisition-app button:hover { background-color: #2c3e50; }
        #land-acquisition-app .owner-row {
            background: #f1f3f4;
            padding: 10px;
            border-radius: 5px;
            margin-bottom: 8px;
        }
        #land-acquisition-app table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
            background: white;
        }
        #land-acquisition-app th, #land-acquisition-app td {
            border: 1px solid #ddd;
            padding: 12px;
            text-align: left;
            font-size: 13px;
        }
        #land-acquisition-app th { background: #34495e; color: white; }
        #land-acquisition-app .btn-group { display: flex; gap: 10px; margin: 20px 0; flex-wrap: wrap; }
        #mermaid-container {
            background: #fff;
            padding: 10px;
            border-radius: 8px;
            min-height: 200px;
            overflow-x: auto;
        }
      .owner-table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 15px;
    background: #f9fafb;
    border: 1px solid #ddd;
}

.owner-table td {
    padding: 6px;
    border: 1px solid #e5e7eb;
}

.owner-table td:first-child {
    font-weight: 600;
    background: #f1f5f9;
    width: 40%;
}

.owner-table input,
.owner-table select {
    width: 100%;
    padding: 5px;
    border: 1px solid #cbd5e1;
    border-radius: 4px;
}
              .container {
            max-width: 1100px;
            margin: auto;
            background: white;
            padding: 30px;
            border-radius: 12px;
            box-shadow: 0 6px 12px rgba(0,0,0,0.1);
        }
        .mermaid {
            background-color: #f9f9f9;
            padding: 20px;
            border-radius: 10px;
            margin: 30px 0;
            overflow-x: auto;
        }
        .note {
            background-color: #e6f7ff;
            border-left: 5px solid #007bff;
            padding: 15px;
            margin: 20px 0;
        }
    &lt;/style&gt;

&lt;div class=&quot;card&quot; style=&quot;border-bottom: 3px solid #2980b9; margin-bottom: 20px;&quot;&gt;
    &lt;h3&gt;Project &amp; Village Configuration&lt;/h3&gt;

    &lt;!-- IMPORT BUTTON --&gt;
    &lt;div style=&quot;margin-bottom:10px;&quot;&gt;
        &lt;input type=&quot;file&quot; id=&quot;importFile&quot; accept=&quot;.json&quot; onchange=&quot;importJSON(event)&quot; style=&quot;display:none;&quot;&gt;
        &lt;button onclick=&quot;document.getElementById(&#39;importFile&#39;).click()&quot; 
            style=&quot;background:#8e44ad; color:white; border:none; padding:10px 15px; border-radius:4px;&quot;&gt;
            Import Backup
        &lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;grid&quot; style=&quot;display:grid; grid-template-columns:1fr 1fr; gap:20px;&quot;&gt;
        
        &lt;!-- PROJECT --&gt;
        &lt;div&gt;
            &lt;label&gt;&lt;strong&gt;1A. Select Active Project:&lt;/strong&gt;&lt;/label&gt;
            &lt;select id=&quot;projectSelect&quot; onchange=&quot;loadProjectData()&quot; style=&quot;width: 100%; padding: 8px; margin-bottom:10px;&quot;&gt;
                &lt;option value=&quot;&quot;&gt;-- Select Project --&lt;/option&gt;
            &lt;/select&gt;

            &lt;div style=&quot;display:flex; gap:5px;&quot;&gt;
                &lt;input type=&quot;text&quot; id=&quot;newProjectName&quot; placeholder=&quot;New Project Name&quot; style=&quot;flex:1; padding:8px;&quot;&gt;
                &lt;button onclick=&quot;createNewProject()&quot; style=&quot;background:#2ecc71; color:white; border:none; padding:8px 12px; border-radius:4px;&quot;&gt;
                    Create
                &lt;/button&gt;
            &lt;/div&gt;
        &lt;/div&gt;

        &lt;!-- VILLAGE --&gt;
        &lt;div&gt;
            &lt;label&gt;&lt;strong&gt;1B. Manage Villages:&lt;/strong&gt;&lt;/label&gt;

            &lt;div style=&quot;display:flex; gap:5px; margin-bottom:10px;&quot;&gt;
                &lt;input type=&quot;text&quot; id=&quot;villageInput&quot; placeholder=&quot;Add Village Name&quot; style=&quot;flex:1; padding:8px;&quot;&gt;
                &lt;button onclick=&quot;addVillageToProject()&quot; style=&quot;background:#3498db; color:white; border:none; padding:8px 12px; border-radius:4px;&quot;&gt;
                    + Add
                &lt;/button&gt;
            &lt;/div&gt;

            &lt;label&gt;&lt;strong&gt;1C. Working Village:&lt;/strong&gt;&lt;/label&gt;
            &lt;select id=&quot;activeVillageSelect&quot; onchange=&quot;changeWorkingVillage()&quot; 
                style=&quot;width: 100%; padding: 8px; border: 2px solid #3498db; font-weight:bold;&quot;&gt;
                &lt;option value=&quot;&quot;&gt;-- Select Village to Start Entry --&lt;/option&gt;
            &lt;/select&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;!-- ENTRY SECTION --&gt;
&lt;div id=&quot;entrySection&quot; style=&quot;display:none;&quot;&gt;
    &lt;div class=&quot;card&quot;&gt;
        
        &lt;div style=&quot;display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;&quot;&gt;
            &lt;h3&gt;2. Gat &amp; Owner Details&lt;/h3&gt;
            &lt;span id=&quot;activeVillageLabel&quot; 
                style=&quot;color:white; font-weight:bold; background:#27ae60; padding:4px 12px; border-radius:20px;&quot;&gt;
            &lt;/span&gt;
        &lt;/div&gt;

        &lt;div id=&quot;gatContainer&quot;&gt;&lt;/div&gt;

        &lt;div style=&quot;display:flex; gap:10px; margin-top:20px;&quot;&gt;
            &lt;button onclick=&quot;addGatRow()&quot; 
                style=&quot;flex:1; background:#7f8c8d; color:white; border:none; padding:12px; border-radius:4px;&quot;&gt;
                + Add Another Gat
            &lt;/button&gt;

            &lt;button onclick=&quot;saveEntry()&quot; 
                style=&quot;flex:2; background:#27ae60; color:white; border:none; padding:12px; font-size:16px; border-radius:4px;&quot;&gt;
                SAVE DATA
            &lt;/button&gt;
        &lt;/div&gt;

    &lt;/div&gt;
&lt;/div&gt;

&lt;!-- SUMMARY --&gt;
&lt;div id=&quot;dashboardSummary&quot; 
    style=&quot;font-weight:bold; font-size:1.2em; text-align:right; margin:15px 0; color:#2c3e50; padding:10px; background:#f8f9fa; border-radius:4px; border-right:5px solid #27ae60;&quot;&gt;
    Total Project Value: ₹0
&lt;/div&gt;

&lt;!-- ACTION BUTTONS --&gt;
&lt;div class=&quot;btn-group&quot; style=&quot;display:flex; gap:10px; margin-bottom:20px;&quot;&gt;
    &lt;button onclick=&quot;exportCSV()&quot; 
        style=&quot;background:#e67e22; color:white; border:none; padding:12px; border-radius:4px; flex:1;&quot;&gt;
        Download Excel
    &lt;/button&gt;

    &lt;button onclick=&quot;exportJSON()&quot; 
        style=&quot;background:#34495e; color:white; border:none; padding:12px; border-radius:4px; flex:1;&quot;&gt;
        Backup
    &lt;/button&gt;

    &lt;button onclick=&quot;resetForm()&quot; 
        style=&quot;background:#95a5a6; color:white; border:none; padding:12px; border-radius:4px; flex:1;&quot;&gt;
        Clear
    &lt;/button&gt;
&lt;/div&gt;

&lt;!-- TABLE --&gt;
&lt;div class=&quot;card&quot;&gt;
    &lt;h3&gt;Master Project Land Records&lt;/h3&gt;

    &lt;div style=&quot;overflow-x:auto;&quot;&gt;
        &lt;table style=&quot;width:100%; border-collapse:collapse;&quot;&gt;
            &lt;thead&gt;
                &lt;tr style=&quot;background:#2c3e50; color:white;&quot;&gt;
                    &lt;th style=&quot;padding:10px;&quot;&gt;Village&lt;/th&gt;
                    &lt;th style=&quot;padding:10px;&quot;&gt;Gat No.&lt;/th&gt;
                    &lt;th style=&quot;padding:10px;&quot;&gt;Owner&lt;/th&gt;
                    &lt;th style=&quot;padding:10px;&quot;&gt;Owned Area&lt;/th&gt;
                    &lt;th style=&quot;padding:10px;&quot;&gt;Acquired Area&lt;/th&gt;
                    &lt;th style=&quot;padding:10px;&quot;&gt;Payable&lt;/th&gt;
                    &lt;th style=&quot;padding:10px;&quot;&gt;Status&lt;/th&gt; &lt;!-- ✅ ADDED --&gt;
                    &lt;th style=&quot;padding:10px;&quot;&gt;Action&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody id=&quot;tableBody&quot;&gt;&lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;!-- VILLAGE SUMMARY --&gt;
&lt;div class=&quot;card&quot;&gt;
    &lt;h3&gt;Village-wise Land Category Summary&lt;/h3&gt;

    &lt;button onclick=&quot;generateVillageSummary()&quot; 
        style=&quot;background:#8e44ad;color:white;border:none;padding:10px 15px;margin-bottom:10px;border-radius:4px;&quot;&gt;
        Generate Summary
    &lt;/button&gt;

    &lt;table style=&quot;width:100%; border-collapse:collapse;&quot;&gt;
        &lt;thead&gt;
            &lt;tr style=&quot;background:#34495e;color:white;&quot;&gt;
                &lt;th&gt;Village&lt;/th&gt;
                &lt;th&gt;Class-1 Area&lt;/th&gt;
                &lt;th&gt;Class-2 Area&lt;/th&gt;
                &lt;th&gt;PESA Area&lt;/th&gt;
                &lt;th&gt;Total Area&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody id=&quot;villageSummaryBody&quot;&gt;&lt;/tbody&gt;
    &lt;/table&gt;
&lt;/div&gt;
  
  &lt;div class=&quot;card&quot;&gt;
    &lt;h3&gt;Village Overview (Project → Villages Only)&lt;/h3&gt;

    &lt;button onclick=&quot;generateVillageOnlyMermaid()&quot; 
        style=&quot;background:#9b59b6;color:white;border:none;padding:10px 15px;border-radius:4px;margin-bottom:10px;&quot;&gt;
        Generate Village Flowchart
    &lt;/button&gt;

    &lt;div class=&quot;mermaid&quot; id=&quot;villageOnlyChart&quot; style=&quot;overflow:auto;&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
  
  &lt;button onclick=&quot;exportVillageOnlySVG()&quot; 
    style=&quot;background:#16a085;color:white;border:none;padding:10px 15px;border-radius:4px;&quot;&gt;
    Export Village Chart (SVG)
&lt;/button&gt;

&lt;!-- MERMAID --&gt;
&lt;div class=&quot;card&quot;&gt;
    &lt;h3&gt;Project Hierarchy View&lt;/h3&gt;

    &lt;button onclick=&quot;generateMermaid()&quot; 
        style=&quot;background:#16a085;color:white;border:none;padding:10px 15px;border-radius:4px;margin-bottom:10px;&quot;&gt;
        Generate Diagram
    &lt;/button&gt;

    &lt;div class=&quot;mermaid&quot; id=&quot;mermaidChart&quot; style=&quot;overflow:auto;&quot;&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;button onclick=&quot;exportMermaidA2()&quot; 
    style=&quot;background:#c0392b;color:white;border:none;padding:10px 15px;border-radius:4px;&quot;&gt;
    Export A2 Print
&lt;/button&gt;
  
 &lt;div class=&quot;card&quot;&gt;
    &lt;h3&gt;Village-wise Detailed Flowcharts&lt;/h3&gt;

    &lt;button onclick=&quot;generateAllVillageCharts()&quot; 
        style=&quot;background:#8e44ad;color:white;border:none;padding:10px 15px;border-radius:4px;margin-bottom:10px;&quot;&gt;
        Generate All Village Charts
    &lt;/button&gt;

    &lt;div id=&quot;allVillageCharts&quot;&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;button onclick=&quot;exportAllVillageChartsSVG()&quot; 
    style=&quot;background:#c0392b;color:white;border:none;padding:10px 15px;border-radius:4px;margin-top:10px;&quot;&gt;
    Export All Charts (SVG)
&lt;/button&gt;
  
  &lt;div style=&quot;font-family:Segoe UI, Arial; line-height:1.6; max-width:900px; margin:auto; color:#2c3e50;&quot;&gt;

    &lt;h1 style=&quot;color:#2c3e50; border-bottom:3px solid #3498db; padding-bottom:5px;&quot;&gt;
        Land Acquisition Management Tool – Complete Guide
    &lt;/h1&gt;

    &lt;p&gt;
        The &lt;b&gt;Land Acquisition Management Tool&lt;/b&gt; is a powerful web-based application designed to manage,
        track, and visualize land acquisition data at project level. It is especially useful for
        engineers, project managers, and government officials handling large-scale infrastructure projects.
    &lt;/p&gt;

    &lt;h2 style=&quot;color:#2980b9;&quot;&gt;1. Key Features&lt;/h2&gt;
    &lt;ul&gt;
        &lt;li&gt;📌 Project-wise and village-wise data management&lt;/li&gt;
        &lt;li&gt;📌 Gat-level land acquisition tracking&lt;/li&gt;
        &lt;li&gt;📌 Owner-wise financial and legal record management&lt;/li&gt;
        &lt;li&gt;📌 Excel (CSV) export with detailed columns&lt;/li&gt;
        &lt;li&gt;📌 JSON backup &amp; restore functionality&lt;/li&gt;
        &lt;li&gt;📌 Mermaid-based hierarchy visualization&lt;/li&gt;
        &lt;li&gt;📌 A2 size printable diagram export&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color:#2980b9;&quot;&gt;2. Workflow Overview&lt;/h2&gt;
    &lt;ol&gt;
        &lt;li&gt;Create a new project&lt;/li&gt;
        &lt;li&gt;Add villages under the project&lt;/li&gt;
        &lt;li&gt;Select a working village&lt;/li&gt;
        &lt;li&gt;Enter Gat details&lt;/li&gt;
        &lt;li&gt;Add owner-wise land and financial data&lt;/li&gt;
        &lt;li&gt;Save and manage records&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h2 style=&quot;color:#2980b9;&quot;&gt;3. Data Structure&lt;/h2&gt;

    &lt;h3&gt;📍 Gat Level Data&lt;/h3&gt;
    &lt;ul&gt;
        &lt;li&gt;Gat Number&lt;/li&gt;
        &lt;li&gt;Land Category (Class-1 / Class-2 / PESA)&lt;/li&gt;
        &lt;li&gt;JMS Status&lt;/li&gt;
        &lt;li&gt;Valuation Status&lt;/li&gt;
        &lt;li&gt;Legal Status&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3&gt;👤 Owner Level Data&lt;/h3&gt;
    &lt;ul&gt;
        &lt;li&gt;Owner Name &amp; Type&lt;/li&gt;
        &lt;li&gt;Owned Area &amp; Acquired Area&lt;/li&gt;
        &lt;li&gt;Payable Amount (Manual Entry)&lt;/li&gt;
        &lt;li&gt;Amount Paid &amp; Balance&lt;/li&gt;
        &lt;li&gt;Draft Sale Deed&lt;/li&gt;
        &lt;li&gt;Registration Fee, Stamp Duty, Paging Fee, Misc Expenses&lt;/li&gt;
        &lt;li&gt;Land Acquisition Cost&lt;/li&gt;
        &lt;li&gt;Payment Date&lt;/li&gt;
        &lt;li&gt;Aadhar &amp; PAN Details&lt;/li&gt;
        &lt;li&gt;Bank Details (Name, IFSC, Account Number)&lt;/li&gt;
        &lt;li&gt;Remarks&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color:#2980b9;&quot;&gt;4. Excel Export Columns&lt;/h2&gt;

    &lt;p&gt;The tool exports complete project data into Excel (CSV) format with the following fields:&lt;/p&gt;

    &lt;div style=&quot;overflow-x:auto;&quot;&gt;
        &lt;table style=&quot;border-collapse:collapse; width:100%;&quot;&gt;
            &lt;tr style=&quot;background:#34495e; color:white;&quot;&gt;
                &lt;th style=&quot;padding:8px;&quot;&gt;Field&lt;/th&gt;
                &lt;th style=&quot;padding:8px;&quot;&gt;Description&lt;/th&gt;
            &lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Village&lt;/td&gt;&lt;td&gt;Village name&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Gat No&lt;/td&gt;&lt;td&gt;Survey/Gat number&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Owner Name&lt;/td&gt;&lt;td&gt;Land owner name&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Category&lt;/td&gt;&lt;td&gt;Land classification&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;JMS Status&lt;/td&gt;&lt;td&gt;Joint Measurement Status&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Valuation Status&lt;/td&gt;&lt;td&gt;Award/valuation progress&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Legal Status&lt;/td&gt;&lt;td&gt;Title verification&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Draft Sale Deed&lt;/td&gt;&lt;td&gt;Document reference&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Registration Fee&lt;/td&gt;&lt;td&gt;Registration cost&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Stamp Duty&lt;/td&gt;&lt;td&gt;Stamp charges&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Paging Fee&lt;/td&gt;&lt;td&gt;Documentation charges&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Miscellaneous&lt;/td&gt;&lt;td&gt;Other expenses&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Land Acquisition Cost&lt;/td&gt;&lt;td&gt;Total cost&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Amount Paid Date&lt;/td&gt;&lt;td&gt;Payment date&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Aadhar Number&lt;/td&gt;&lt;td&gt;Identity proof&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;PAN Number&lt;/td&gt;&lt;td&gt;Tax ID&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Bank Details&lt;/td&gt;&lt;td&gt;Payment account details&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;&lt;td&gt;Remarks&lt;/td&gt;&lt;td&gt;Additional notes&lt;/td&gt;&lt;/tr&gt;
        &lt;/table&gt;
    &lt;/div&gt;

    &lt;h2 style=&quot;color:#2980b9;&quot;&gt;5. Mermaid Hierarchy Visualization&lt;/h2&gt;

    &lt;p&gt;
        The tool generates a &lt;b&gt;visual flowchart&lt;/b&gt; using Mermaid.js representing:
    &lt;/p&gt;

    &lt;ul&gt;
        &lt;li&gt;🏗️ Project&lt;/li&gt;
        &lt;li&gt;🏡 Villages&lt;/li&gt;
        &lt;li&gt;📍 Gat Numbers&lt;/li&gt;
        &lt;li&gt;👤 Owner Details&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;
        Each node includes financial, legal, and identity details, making it extremely useful
        for presentations and reporting.
    &lt;/p&gt;

    &lt;h3&gt;🖨️ A2 Print Export&lt;/h3&gt;
    &lt;p&gt;
        The diagram can be exported in &lt;b&gt;A2 size SVG format&lt;/b&gt;, allowing full-scale printing
        for large datasets such as highway or irrigation projects.
    &lt;/p&gt;

    &lt;h2 style=&quot;color:#2980b9;&quot;&gt;6. Village-wise Summary&lt;/h2&gt;

    &lt;p&gt;
        The tool automatically generates summary reports based on land category:
    &lt;/p&gt;

    &lt;ul&gt;
        &lt;li&gt;Class-1 Area&lt;/li&gt;
        &lt;li&gt;Class-2 Area&lt;/li&gt;
        &lt;li&gt;PESA Area&lt;/li&gt;
        &lt;li&gt;Total Acquired Area&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color:#2980b9;&quot;&gt;7. Backup &amp; Restore&lt;/h2&gt;

    &lt;ul&gt;
        &lt;li&gt;Export full project as JSON backup&lt;/li&gt;
        &lt;li&gt;Import data anytime&lt;/li&gt;
        &lt;li&gt;Safe data storage using IndexedDB (browser-based)&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color:#2980b9;&quot;&gt;8. Advantages&lt;/h2&gt;

    &lt;ul&gt;
        &lt;li&gt;✔ No server required (works offline)&lt;/li&gt;
        &lt;li&gt;✔ Fast and responsive&lt;/li&gt;
        &lt;li&gt;✔ Highly customizable&lt;/li&gt;
        &lt;li&gt;✔ Ideal for government and EPC projects&lt;/li&gt;
        &lt;li&gt;✔ Scalable for thousands of records&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color:#2980b9;&quot;&gt;9. Conclusion&lt;/h2&gt;

    &lt;p&gt;
        This Land Acquisition Tool provides a digital solution for managing
        complex land records, financial tracking, and legal status in a structured manner.
        With visualization and export features, it improves decision-making and reporting efficiency.
    &lt;/p&gt;

&lt;/div&gt;
  
  &lt;div class=&quot;container&quot;&gt;

&lt;h2&gt;Interactive Flowchart for detailed Land Acquisition Procedure&lt;/h2&gt;

&lt;div class=&quot;mermaid&quot;&gt;
flowchart TD
    A[Start: Project Planning and DPR Finalization&lt;br/&gt;Land Requirements Identified]
    --&gt; B[Appointment of Competent Authority for Land Acquisition - CALA]

    B --&gt; C[Service of Individual Notices&lt;br/&gt;Commonly called 3A notices&lt;br/&gt;to Known Landowners]

    C --&gt; D[Publication of Section 3A Notification&lt;br/&gt;Intention to Acquire Land&lt;br/&gt;e-Gazette plus two local newspapers]

    D --&gt; E[Market Value Fixed as on 3A Date&lt;br/&gt;12 percent annual interest starts&lt;br/&gt;Survey and entry permitted under Section 3B]

    E --&gt; F[Objections Invited&lt;br/&gt;Within 21 days&lt;br/&gt;Limited to necessity or public purpose]

    F --&gt; G{CALA hears objections&lt;br/&gt;Conducts inquiry and submits report}

    G --&gt;|Objections upheld| H((Process revised or dropped))

    G --&gt;|Objections rejected| I[(Publication of Section 3D Notification&lt;br/&gt;Declaration of acquisition&lt;br/&gt;Within one year of 3A excluding stays)]

    I --&gt; J([Land vests absolutely in Central Government&lt;br/&gt;Free from all encumbrances])

    J --&gt; K([CALA determines compensation award&lt;br/&gt;Section 3G&lt;br/&gt;Market value plus multiplier&lt;br/&gt;100 percent solatium plus damages])

    K --&gt; L([Deposit of compensation by NHAI or Central Government&lt;br/&gt;Section 3H])

    L --&gt; M([Direct payment to landowners bank accounts&lt;br/&gt;Via Bhoomi Rashi Portal and PFMS])

    M --&gt; N([Notice to surrender possession&lt;br/&gt;Within 60 days under Section 3E])

    N --&gt; O([Physical possession taken&lt;br/&gt;Handed over to executing agency])

    O --&gt; P{Dispute on compensation award}

    P --&gt;|Yes| Q[Application for arbitration&lt;br/&gt;Sections 3G-5 and 3J&lt;br/&gt;Arbitrator appointed by Central Government]

    Q --&gt; R[Arbitrator decision&lt;br/&gt;Final with limited court intervention]

    P --&gt;|No| S(End of land acquisition process)

    O --&gt; S

    style A fill:#e6f7ff,stroke:#333
    style H fill:#ffcccc,stroke:#333
    style O fill:#d4edda,stroke:#333
    style S fill:#d4edda,stroke:#333
    style R fill:#fff3cd,stroke:#333
&lt;/div&gt;

&lt;div class=&quot;note&quot;&gt;
    &lt;strong&gt;Key Notes (as of January 2026):&lt;/strong&gt;
    &lt;ul&gt;
        &lt;li&gt;The entire process is digitized via the &lt;strong&gt;Bhoomi Rashi Portal&lt;/strong&gt; for notifications, approvals, and payments.&lt;/li&gt;
        &lt;li&gt;No Social Impact Assessment, landowner consent, or full Rehabilitation &amp; Resettlement required (unlike general RFCTLARR Act).&lt;/li&gt;
        &lt;li&gt;NHAI&#39;s 336-day timeline framework (introduced April 2025) applies post-3D for award, payment, and possession.&lt;/li&gt;
        &lt;li&gt;Compensation is enhanced: Market value × multiplier + 100% solatium + damages + 12% interest.&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;

&lt;h1&gt;Detailed Land Acquisition Procedure under the National Highways Act, 1956&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;National Highways Act, 1956&lt;/strong&gt; (NH Act) provides a dedicated and streamlined framework for acquiring land specifically for the building, maintenance, management, or operation of &lt;strong&gt;national highways&lt;/strong&gt; in India. The core provisions are contained in &lt;strong&gt;Sections 3A to 3J&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Since a Central Government notification dated &lt;strong&gt;August 28, 2015&lt;/strong&gt;, the determination of compensation follows the &lt;strong&gt;First Schedule&lt;/strong&gt; of the &lt;strong&gt;Right to Fair Compensation and Transparency in Land Acquisition, Rehabilitation and Resettlement Act, 2013&lt;/strong&gt; (RFCTLARR Act). This includes market value calculation, multiplication factors (up to 2x in rural areas, 1x in urban), and 100% solatium. However, the procedural steps remain governed by the NH Act, and the full Rehabilitation &amp; Resettlement (R&amp;R) provisions (Second Schedule of RFCTLARR) do &lt;strong&gt;not&lt;/strong&gt; apply.&lt;/p&gt;

&lt;p&gt;The process is overseen by the &lt;strong&gt;National Highways Authority of India (NHAI)&lt;/strong&gt; or other agencies (e.g., NHIDCL, State PWDs). The &lt;strong&gt;Competent Authority for Land Acquisition (CALA)&lt;/strong&gt;—typically a senior revenue officer appointed by the Central Government—plays a pivotal role. The entire workflow is now fully digitized through the &lt;strong&gt;Bhoomi Rashi Portal&lt;/strong&gt; (launched in 2018), enabling online notification processing, approvals, and direct compensation payments via PFMS integration.&lt;/p&gt;

&lt;div class=&quot;note&quot;&gt;
    &lt;strong&gt;As of January 2026:&lt;/strong&gt; No major amendments to the NH Act have been enacted in 2025. Proposals (circulated in March 2025) to return unused acquired land after 5 years and other reforms are still pending Cabinet/Parliamentary approval.
&lt;/div&gt;

&lt;h2&gt;Step-by-Step Procedure&lt;/h2&gt;

&lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Preliminary Planning and Appointment of Authorities&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;Land requirements are identified during the Detailed Project Report (DPR) stage, including alignment finalization and joint measurement surveys (standardized templates introduced in 2025 for accuracy).&lt;/li&gt;
            &lt;li&gt;Central Government appoints the &lt;strong&gt;Competent Authority (CALA)&lt;/strong&gt; for the project stretch.&lt;/li&gt;
            &lt;li&gt;Individual notices (commonly referred to as &lt;strong&gt;3a notices&lt;/strong&gt;) are served to known landowners and interested persons, informing them of the proposed acquisition and inviting early feedback/objections.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;

    &lt;li&gt;&lt;strong&gt;Section 3A: Intention to Acquire Land (Preliminary Notification)&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;The Central Government publishes the notification in the Official e-Gazette and two local newspapers.&lt;/li&gt;
            &lt;li&gt;It details the land parcels, purpose, and summary.&lt;/li&gt;
            &lt;li&gt;Key triggers from this date:
                &lt;ul&gt;
                    &lt;li&gt;Determination of &lt;strong&gt;market value&lt;/strong&gt; for compensation.&lt;/li&gt;
                    &lt;li&gt;Additional &lt;strong&gt;12% interest per annum&lt;/strong&gt; on market value until award or possession.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/li&gt;
            &lt;li&gt;Authorized officials may enter the land for surveys (Section 3B).&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;

    &lt;li&gt;&lt;strong&gt;Section 3C: Hearing of Objections&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;Interested persons can file objections within &lt;strong&gt;21 days&lt;/strong&gt; of 3A publication.&lt;/li&gt;
            &lt;li&gt;Objections are limited to the necessity or public purpose of the acquisition.&lt;/li&gt;
            &lt;li&gt;CALA conducts an inquiry and submits a report to the Central Government.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;

    &lt;li&gt;&lt;strong&gt;Section 3D: Declaration of Acquisition (Final Notification)&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;After considering objections (if any), the Central Government publishes the declaration in the e-Gazette.&lt;/li&gt;
            &lt;li&gt;Land vests absolutely in the Central Government &lt;strong&gt;free from all encumbrances&lt;/strong&gt; on this date.&lt;/li&gt;
            &lt;li&gt;Must be issued within &lt;strong&gt;1 year&lt;/strong&gt; of 3A (excluding periods of stay orders); otherwise, proceedings lapse.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;

    &lt;li&gt;&lt;strong&gt;Sections 3E/3F: Power to Take Possession&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;Post-3D and deposit of compensation, CALA directs landowners to surrender possession within &lt;strong&gt;60 days&lt;/strong&gt;.&lt;/li&gt;
            &lt;li&gt;Limited entry for urgent construction works is permitted even earlier (Section 3F).&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;

    &lt;li&gt;&lt;strong&gt;Section 3G: Determination and Declaration of Compensation (Award)&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;CALA calculates and declares the award, considering:
                &lt;ul&gt;
                    &lt;li&gt;Market value (higher of guideline rates or recent sales) as on 3A date.&lt;/li&gt;
                    &lt;li&gt;Multiplication factor and 100% solatium (per RFCTLARR First Schedule).&lt;/li&gt;
                    &lt;li&gt;Damages for standing crops, trees, structures, severance, etc.&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/li&gt;
            &lt;li&gt;Award specifies apportionment among interested parties.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;

    &lt;li&gt;&lt;strong&gt;Section 3H: Deposit and Payment&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;Amount is deposited by the Central Government/NHAI with CALA.&lt;/li&gt;
            &lt;li&gt;Direct disbursement to landowners&#39; bank accounts via Bhoomi Rashi (often 80-100% upfront in practice).&lt;/li&gt;
            &lt;li&gt;Possession is generally taken only after payment.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;

    &lt;li&gt;&lt;strong&gt;Dispute Resolution (Sections 3G(5) and 3J)&lt;/strong&gt;
        &lt;ul&gt;
            &lt;li&gt;Dissatisfied parties can seek &lt;strong&gt;arbitration&lt;/strong&gt; before a Central Government-appointed arbitrator.&lt;/li&gt;
            &lt;li&gt;Arbitrator&#39;s decision is final, with limited scope for court intervention.&lt;/li&gt;
            &lt;li&gt;Enhanced awards may include interest.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Key Features and Recent Developments (as of January 2026)&lt;/h2&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;336-Day Timeline Framework&lt;/strong&gt;: Introduced via NHAI Policy Circular dated April 9, 2025, this mandates optimum completion of post-3D processes (award, payment, possession) within 336 days, with weekly/fortnightly monitoring and escalation protocols.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;No SIA, Consent, or Full R&amp;R&lt;/strong&gt;: Unlike general acquisitions under RFCTLARR, these are not required, making the process faster.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Digital Transformation&lt;/strong&gt;: Mandatory use of &lt;strong&gt;Bhoomi Rashi Portal&lt;/strong&gt; for all notifications, approvals, and payments—significantly reducing timelines and enhancing transparency.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Proposed Amendments (Pending)&lt;/strong&gt;: 2025 proposals include provisions for returning unused land after 5 years and restrictions on post-notification transactions to curb speculation.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Urgency Provisions&lt;/strong&gt;: Rarely invoked but available for national defense/emergencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This NH Act procedure is notably faster than the full RFCTLARR process, facilitating rapid highway development. Digitization and the 2025 timeline framework have further reduced delays.&lt;/p&gt;

&lt;p&gt;For project-specific status, refer to the &lt;a href=&quot;https://bhoomirashi.gov.in/&quot; target=&quot;_blank&quot;&gt;Bhoomi Rashi Portal&lt;/a&gt; or official MoRTH/NHAI guidelines. &lt;/p&gt;

&lt;script&gt;
/* ================= DATABASE ================= */
let db;
let editingIndex = null;

const request = indexedDB.open(&quot;LandAcqBloggerDB&quot;, 1);

request.onupgradeneeded = (e) =&gt; {
    db = e.target.result;
    if (!db.objectStoreNames.contains(&quot;projects&quot;)) {
        db.createObjectStore(&quot;projects&quot;, { keyPath: &quot;id&quot;, autoIncrement: true });
    }
};

request.onsuccess = (e) =&gt; { 
    db = e.target.result; 
    refreshProjectList();
    addGatRow(); // UX improvement
};

/* ================= PROJECT ================= */
function createNewProject() {
    const name = document.getElementById(&#39;newProjectName&#39;).value.trim();
    if (!name) return alert(&quot;Project Name required&quot;);

    const tx = db.transaction(&quot;projects&quot;, &quot;readwrite&quot;);
    tx.objectStore(&quot;projects&quot;).add({ name, entries: [], villages: [] });

    tx.oncomplete = () =&gt; {
        document.getElementById(&#39;newProjectName&#39;).value = &quot;&quot;;
        refreshProjectList();
    };
}

function refreshProjectList() {
    const select = document.getElementById(&#39;projectSelect&#39;);
    select.innerHTML = &#39;&lt;option value=&quot;&quot;&gt;-- Select Project --&lt;/option&gt;&#39;;

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).openCursor().onsuccess = (e) =&gt; {
        const cursor = e.target.result;
        if (cursor) {
            let opt = document.createElement(&#39;option&#39;);
            opt.value = cursor.value.id;
            opt.text = cursor.value.name;
            select.add(opt);
            cursor.continue();
        }
    };
}

/* ================= VILLAGE ================= */
function addVillageToProject() {
    const id = parseInt(document.getElementById(&#39;projectSelect&#39;).value);
    const vInput = document.getElementById(&#39;villageInput&#39;);
    const vName = vInput.value.trim();

    if (!id) return alert(&quot;Select a Project first&quot;);
    if (!vName) return alert(&quot;Enter Village Name&quot;);

    const tx = db.transaction(&quot;projects&quot;, &quot;readwrite&quot;);
    const store = tx.objectStore(&quot;projects&quot;);

    store.get(id).onsuccess = (e) =&gt; {
        const p = e.target.result;

        if (!p.villages) p.villages = [];

        const exists = p.villages.map(v =&gt; v.toLowerCase()).includes(vName.toLowerCase());

        if (!exists) {
            p.villages.push(vName);
            store.put(p).onsuccess = () =&gt; {
                updateVillageDropdown(p.villages);
                vInput.value = &quot;&quot;;
            };
        } else {
            alert(&quot;Village already exists&quot;);
        }
    };
}

function updateVillageDropdown(villages) {
    const select = document.getElementById(&#39;activeVillageSelect&#39;);
    select.innerHTML = &#39;&lt;option value=&quot;&quot;&gt;-- Select Village to Start Entry --&lt;/option&gt;&#39;;

    villages.sort().forEach(v =&gt; {
        let opt = document.createElement(&#39;option&#39;);
        opt.value = v;
        opt.text = v;
        select.add(opt);
    });
}

function changeWorkingVillage(skipReset = false) {
    const village = document.getElementById(&#39;activeVillageSelect&#39;).value;
    const entrySection = document.getElementById(&#39;entrySection&#39;);
    const label = document.getElementById(&#39;activeVillageLabel&#39;);

    if (village) {
        entrySection.style.display = &quot;block&quot;;
        label.innerText = &quot;Village: &quot; + village;

        // 🔥 Skip reset during edit
        if (!skipReset) {
            resetForm(false);
        }
    } else {
        entrySection.style.display = &quot;none&quot;;
    }
}
/* ================= GAT UI ================= */
function addGatRow() {
    const div = document.createElement(&#39;div&#39;);
    div.className = &#39;gat-entry card&#39;;
    div.style = &#39;background:#fdfdfd;border:1px solid #ddd;margin-top:15px;padding:15px;position:relative;&#39;;

    div.innerHTML = `
        &lt;!-- REMOVE BUTTON --&gt;
        &lt;button onclick=&quot;this.closest(&#39;.gat-entry&#39;).remove()&quot; 
            style=&quot;position:absolute;top:10px;right:10px;background:#e74c3c;color:white;border:none;border-radius:4px;padding:2px 8px;cursor:pointer;&quot;&gt;
            X
        &lt;/button&gt;

        &lt;!-- GAT BASIC DETAILS --&gt;
        &lt;h4 style=&quot;margin-bottom:10px;&quot;&gt;Gat Details&lt;/h4&gt;

        &lt;div class=&quot;grid&quot; style=&quot;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-bottom:15px;&quot;&gt;
            
            &lt;div&gt;
                &lt;label&gt;Gat Number&lt;/label&gt;
                &lt;input type=&quot;text&quot; class=&quot;gatNumber&quot; placeholder=&quot;Enter Gat No&quot; style=&quot;width:100%;&quot;&gt;
            &lt;/div&gt;

            &lt;div&gt;
                &lt;label&gt;Land Category&lt;/label&gt;
                &lt;select class=&quot;landCategory&quot; style=&quot;width:100%;&quot;&gt;
                    &lt;option value=&quot;Class-1&quot;&gt;Class-1&lt;/option&gt;
                    &lt;option value=&quot;Class-2&quot;&gt;Class-2&lt;/option&gt;
                    &lt;option value=&quot;PESA&quot;&gt;PESA&lt;/option&gt;
                &lt;/select&gt;
            &lt;/div&gt;

        &lt;/div&gt;

        &lt;!-- PROCEDURE STATUS --&gt;
        &lt;h4 style=&quot;margin-bottom:8px;&quot;&gt;Land Acquisition Status&lt;/h4&gt;

        &lt;div class=&quot;grid&quot; style=&quot;grid-template-columns:1fr 1fr 1fr; gap:10px; margin-bottom:15px; background:#f8f9fa; padding:10px; border-radius:6px;&quot;&gt;
            
            &lt;div&gt;
                &lt;label&gt;JMS Status&lt;/label&gt;
                &lt;select class=&quot;checkJMS&quot; style=&quot;width:100%;&quot;&gt;
                    &lt;option value=&quot;Pending&quot;&gt;Pending&lt;/option&gt;
                    &lt;option value=&quot;Ongoing&quot;&gt;Ongoing / Verification&lt;/option&gt;
                    &lt;option value=&quot;Completed&quot;&gt;Completed (Final Area)&lt;/option&gt;
                &lt;/select&gt;
            &lt;/div&gt;

            &lt;div&gt;
                &lt;label&gt;Valuation Status&lt;/label&gt;
                &lt;select class=&quot;checkValuation&quot; style=&quot;width:100%;&quot;&gt;
                    &lt;option value=&quot;Awaited&quot;&gt;Awaited&lt;/option&gt;
                    &lt;option value=&quot;Draft&quot;&gt;Draft Prepared&lt;/option&gt;
                    &lt;option value=&quot;Declared&quot;&gt;Declared (Awarded)&lt;/option&gt;
                &lt;/select&gt;
            &lt;/div&gt;

            &lt;div&gt;
                &lt;label&gt;Legal Status&lt;/label&gt;
                &lt;select class=&quot;checkLegal&quot; style=&quot;width:100%;&quot;&gt;
                    &lt;option value=&quot;Clear&quot;&gt;Clear Title&lt;/option&gt;
                    &lt;option value=&quot;Disputed&quot;&gt;Disputed / Court Case&lt;/option&gt;
                    &lt;option value=&quot;In-Progress&quot;&gt;In-Progress&lt;/option&gt;
                &lt;/select&gt;
            &lt;/div&gt;

        &lt;/div&gt;

        &lt;!-- OWNERS SECTION --&gt;
        &lt;h4 style=&quot;margin-bottom:8px;&quot;&gt;Owner Details&lt;/h4&gt;

        &lt;div class=&quot;ownerInputs&quot;&gt;&lt;/div&gt;

        &lt;button onclick=&quot;addOwnerRow(this)&quot; 
            style=&quot;background:#95a5a6;color:white;border:none;padding:6px 12px;border-radius:4px;margin-top:10px;cursor:pointer;&quot;&gt;
            + Add Owner
        &lt;/button&gt;
    `;

    document.getElementById(&#39;gatContainer&#39;).appendChild(div);

    // Add first owner row by default
    addOwnerRow(div.querySelector(&#39;.ownerInputs&#39;));
}
  
 function editGat(entryIndex) {
    const projectId = parseInt(document.getElementById(&#39;projectSelect&#39;).value);
    if (!projectId) return alert(&quot;Select project first&quot;);

    editingIndex = entryIndex;

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(projectId).onsuccess = (e) =&gt; {
        const project = e.target.result;
        const entry = project.entries[entryIndex];
        if (!entry) return alert(&quot;Entry not found&quot;);

        // Set village
        document.getElementById(&#39;activeVillageSelect&#39;).value = entry.village;
        changeWorkingVillage(true);  // skip reset

        const container = document.getElementById(&#39;gatContainer&#39;);
        container.innerHTML = &quot;&quot;;   // Clear everything

        // Create fresh Gat row
        addGatRow();
        const gatCard = container.querySelector(&#39;.gat-entry&#39;);
        if (!gatCard) return;

        // Fill Gat fields
        gatCard.querySelector(&#39;.gatNumber&#39;).value = entry.gat || &#39;&#39;;
        gatCard.querySelector(&#39;.landCategory&#39;).value = entry.category || &quot;Class-1&quot;;
        gatCard.querySelector(&#39;.checkJMS&#39;).value = entry.jmsStatus || &quot;Pending&quot;;
        gatCard.querySelector(&#39;.checkValuation&#39;).value = entry.valuationStatus || &quot;Awaited&quot;;
        gatCard.querySelector(&#39;.checkLegal&#39;).value = entry.legalStatus || &quot;Clear&quot;;

        // Clear default owner and load real ones
        const oContainer = gatCard.querySelector(&#39;.ownerInputs&#39;);
        oContainer.innerHTML = &quot;&quot;;

        (entry.owners || []).forEach(o =&gt; addOwnerRowForEdit(oContainer, o));

        // Update Save button
        const saveBtn = document.querySelector(&#39;button[onclick=&quot;saveEntry()&quot;]&#39;);
        if (saveBtn) {
            saveBtn.innerText = &quot;UPDATE RECORD&quot;;
            saveBtn.style.background = &quot;#3498db&quot;;
        }

        window.scrollTo({ top: 0, behavior: &#39;smooth&#39; });
    };
}

function addOwnerRowForEdit(container, o) {
    const div = document.createElement(&#39;div&#39;);
    div.className = &#39;owner-row&#39;;

    div.innerHTML = `
        &lt;div style=&quot;display:grid; grid-template-columns: 180px 1fr; gap:8px; align-items:center;&quot;&gt;

            &lt;label&gt;Owner Name&lt;/label&gt;
            &lt;input type=&quot;text&quot; class=&quot;ownerName&quot;&gt;

            &lt;label&gt;Owner Type&lt;/label&gt;
            &lt;select class=&quot;ownerType&quot;&gt;
                &lt;option value=&quot;Private&quot;&gt;Private&lt;/option&gt;
                &lt;option value=&quot;Govt&quot;&gt;Govt&lt;/option&gt;
            &lt;/select&gt;

            &lt;label&gt;Owned Area&lt;/label&gt;
            &lt;input type=&quot;number&quot; class=&quot;totalArea&quot;&gt;

            &lt;label&gt;Acquired Area&lt;/label&gt;
            &lt;input type=&quot;number&quot; class=&quot;ownerArea&quot;&gt;

            &lt;label&gt;Payable Amount (₹)&lt;/label&gt;
            &lt;input type=&quot;number&quot; class=&quot;amtPayable&quot;&gt;

            &lt;label&gt;Amount Paid (₹)&lt;/label&gt;
            &lt;input type=&quot;number&quot; class=&quot;amtPaid&quot;&gt;
            
            &lt;label&gt;Repayment of Bank Loan (₹)&lt;/label&gt;
			&lt;input type=&quot;number&quot; class=&quot;loanRepayment&quot;&gt;

            &lt;label&gt;Paid Date&lt;/label&gt;
            &lt;input type=&quot;date&quot; class=&quot;paidDate&quot;&gt;

            &lt;label&gt;Draft Sale Deed&lt;/label&gt;
            &lt;input type=&quot;text&quot; class=&quot;draftDeed&quot;&gt;

            &lt;label&gt;Registration Fee (₹)&lt;/label&gt;
            &lt;input type=&quot;number&quot; class=&quot;regFee&quot;&gt;

            &lt;label&gt;Stamp Duty (₹)&lt;/label&gt;
            &lt;input type=&quot;number&quot; class=&quot;stampDuty&quot;&gt;

            &lt;label&gt;Paging Fee (₹)&lt;/label&gt;
            &lt;input type=&quot;number&quot; class=&quot;pagingFee&quot;&gt;

            &lt;label&gt;Miscellaneous (₹)&lt;/label&gt;
            &lt;input type=&quot;number&quot; class=&quot;misc&quot;&gt;

            &lt;label&gt;Land Acquisition Cost (₹)&lt;/label&gt;
            &lt;input type=&quot;number&quot; class=&quot;laCost&quot;&gt;

            &lt;label&gt;Aadhar Number&lt;/label&gt;
            &lt;input type=&quot;text&quot; class=&quot;aadhar&quot;&gt;

            &lt;label&gt;PAN Number&lt;/label&gt;
            &lt;input type=&quot;text&quot; class=&quot;pan&quot;&gt;

            &lt;label&gt;Bank Name&lt;/label&gt;
            &lt;input type=&quot;text&quot; class=&quot;bank&quot;&gt;

            &lt;label&gt;IFSC Code&lt;/label&gt;
            &lt;input type=&quot;text&quot; class=&quot;ifsc&quot;&gt;

            &lt;label&gt;Account Number&lt;/label&gt;
            &lt;input type=&quot;text&quot; class=&quot;account&quot;&gt;

            &lt;label&gt;Remarks&lt;/label&gt;
            &lt;input type=&quot;text&quot; class=&quot;remarks&quot;&gt;

        &lt;/div&gt;

        &lt;button onclick=&quot;this.parentElement.remove()&quot; 
            style=&quot;margin-top:10px;background:#e74c3c;color:white;border:none;padding:5px 10px;border-radius:4px;&quot;&gt;
            Remove Owner
        &lt;/button&gt;
    `;

    container.appendChild(div);
}
/* ================= CALC ================= */


/* ================= SAVE ================= */
function saveEntry() {
    const projectId = parseInt(document.getElementById(&#39;projectSelect&#39;).value);
    const villageName = document.getElementById(&#39;activeVillageSelect&#39;).value;

    if (!projectId || !villageName) {
        alert(&quot;Select Project &amp; Village&quot;);
        return;
    }

    const newGats = [];

    document.querySelectorAll(&#39;.gat-entry&#39;).forEach(ge =&gt; {

        const gatNo = ge.querySelector(&#39;.gatNumber&#39;).value.trim();
        if (!gatNo) return;

        const owners = [];

        ge.querySelectorAll(&#39;.owner-row&#39;).forEach(or =&gt; {
            const name = or.querySelector(&#39;.ownerName&#39;).value.trim();

            if (name) {
                owners.push({
                    name: name,
                    type: or.querySelector(&#39;.ownerType&#39;)?.value || &quot;Private&quot;,

                    totalArea: parseFloat(or.querySelector(&#39;.totalArea&#39;).value) || 0,
                    area: parseFloat(or.querySelector(&#39;.ownerArea&#39;).value) || 0,
                    payable: parseFloat(or.querySelector(&#39;.amtPayable&#39;).value) || 0,
                    paid: parseFloat(or.querySelector(&#39;.amtPaid&#39;)?.value) || 0,
                  	loanRepayment: parseFloat(or.querySelector(&#39;.loanRepayment&#39;)?.value) || 0,

                    draftDeed: or.querySelector(&#39;.draftDeed&#39;)?.value || &quot;&quot;,
                    regFee: parseFloat(or.querySelector(&#39;.regFee&#39;)?.value) || 0,
                    stampDuty: parseFloat(or.querySelector(&#39;.stampDuty&#39;)?.value) || 0,
                    pagingFee: parseFloat(or.querySelector(&#39;.pagingFee&#39;)?.value) || 0,
                    misc: parseFloat(or.querySelector(&#39;.misc&#39;)?.value) || 0,
                    laCost: parseFloat(or.querySelector(&#39;.laCost&#39;)?.value) || 0,

                    paidDate: or.querySelector(&#39;.paidDate&#39;)?.value || &quot;&quot;,

                    aadhar: or.querySelector(&#39;.aadhar&#39;)?.value || &quot;&quot;,
                    pan: or.querySelector(&#39;.pan&#39;)?.value || &quot;&quot;,

                    bank: or.querySelector(&#39;.bank&#39;)?.value || &quot;&quot;,
                    ifsc: or.querySelector(&#39;.ifsc&#39;)?.value || &quot;&quot;,
                    account: or.querySelector(&#39;.account&#39;)?.value || &quot;&quot;,

                    remarks: or.querySelector(&#39;.remarks&#39;)?.value || &quot;&quot;
                });
            }
        });

        if (owners.length &gt; 0) {
            newGats.push({
                village: villageName,
                gat: gatNo,
                category: ge.querySelector(&#39;.landCategory&#39;)?.value || &quot;Class-1&quot;,

                jmsStatus: ge.querySelector(&#39;.checkJMS&#39;)?.value || &quot;Pending&quot;,
                valuationStatus: ge.querySelector(&#39;.checkValuation&#39;)?.value || &quot;Awaited&quot;,
                legalStatus: ge.querySelector(&#39;.checkLegal&#39;)?.value || &quot;Clear&quot;,

                owners: owners
            });
        }
    });

    if (newGats.length === 0) {
        alert(&quot;No valid data&quot;);
        return;
    }

    const tx = db.transaction(&quot;projects&quot;, &quot;readwrite&quot;);
    const store = tx.objectStore(&quot;projects&quot;);

    store.get(projectId).onsuccess = (e) =&gt; {
        const p = e.target.result;
        if (!p.entries) p.entries = [];

        // 🔥 EDIT MODE (REPLACE)
        if (editingIndex !== null &amp;&amp; editingIndex !== undefined) {

            if (newGats.length !== 1) {
                alert(&quot;Edit mode allows only one Gat&quot;);
                return;
            }

            // ✅ Replace exact entry
            p.entries.splice(editingIndex, 1, newGats[0]);

            alert(&quot;Entry updated successfully&quot;);

        } else {
            // ✅ NEW ENTRY
            p.entries.push(...newGats);
            alert(&quot;New Gat added&quot;);
        }

        // Reset edit mode AFTER save
        editingIndex = null;

        store.put(p).onsuccess = () =&gt; {
            renderTable(p.entries);
            resetForm(false);
        };
    };
}
/* ================= DELETE ================= */
function deleteOwner(entryIndex, ownerIndex) {
    const projectId = parseInt(document.getElementById(&#39;projectSelect&#39;).value);

    const tx = db.transaction(&quot;projects&quot;, &quot;readwrite&quot;);
    const store = tx.objectStore(&quot;projects&quot;);

    store.get(projectId).onsuccess = (e) =&gt; {
        const p = e.target.result;

        p.entries[entryIndex].owners.splice(ownerIndex, 1);

        if (p.entries[entryIndex].owners.length === 0) {
            p.entries.splice(entryIndex, 1);
        }

        store.put(p).onsuccess = () =&gt; renderTable(p.entries);
    };
}

/* ================= TABLE ================= */
function renderTable(entries) {
    const tbody = document.getElementById(&#39;tableBody&#39;);
    tbody.innerHTML = &quot;&quot;;
    let total = 0;

    (entries || []).forEach((ent, eIdx) =&gt; {

        (ent.owners || []).forEach((o, oIdx) =&gt; {

            total += o.payable || 0;
            const isFirst = oIdx === 0;

            tbody.innerHTML += `
                &lt;tr style=&quot;${isFirst ? &#39;border-top:2px solid #ddd;&#39; : &#39;&#39;}&quot;&gt;

                    &lt;td&gt;${isFirst ? ent.village : &#39;&#39;}&lt;/td&gt;
                    &lt;td&gt;${isFirst ? ent.gat : &#39;&#39;}&lt;/td&gt;

                    &lt;td&gt;
                        ${o.name} 
                        &lt;small&gt;(${o.type || &#39;Private&#39;})&lt;/small&gt;
                    &lt;/td&gt;

                    &lt;td&gt;${(o.totalArea || 0).toFixed(4)}&lt;/td&gt;
                    &lt;td&gt;${(o.area || 0).toFixed(4)}&lt;/td&gt;

                    &lt;td style=&quot;text-align:right;&quot;&gt;
                        ₹${(o.payable || 0).toLocaleString(&#39;en-IN&#39;)}
                    &lt;/td&gt;

                    &lt;!-- ✅ STATUS COLUMN --&gt;
                    &lt;td&gt;
                        ${isFirst ? `
                            &lt;small&gt;
                                JMS: ${ent.jmsStatus}&lt;br&gt;
                                Val: ${ent.valuationStatus}&lt;br&gt;
                                Legal: ${ent.legalStatus}
                            &lt;/small&gt;
                        ` : &#39;&#39;}
                    &lt;/td&gt;

                    &lt;!-- ACTION --&gt;
                    &lt;td&gt;
                        ${isFirst ? `
                            &lt;button onclick=&quot;editGat(${eIdx})&quot;
                                style=&quot;background:#3498db;color:white;border:none;padding:3px 6px;margin-right:5px;&quot;&gt;
                                Edit
                            &lt;/button&gt;
                        ` : &#39;&#39;}

                        &lt;button onclick=&quot;deleteOwner(${eIdx},${oIdx})&quot;
                            style=&quot;background:#e74c3c;color:white;border:none;padding:3px 6px;&quot;&gt;
                            Del
                        &lt;/button&gt;
                    &lt;/td&gt;

                &lt;/tr&gt;
            `;
        });
    });

    document.getElementById(&#39;dashboardSummary&#39;).innerHTML =
        `Total Project Value: ₹${total.toLocaleString(&#39;en-IN&#39;)}`;
}

/* ================= LOAD ================= */
function loadProjectData() {
    const id = parseInt(document.getElementById(&#39;projectSelect&#39;).value);

    document.getElementById(&#39;activeVillageSelect&#39;).innerHTML =
        &#39;&lt;option value=&quot;&quot;&gt;-- Select Village --&lt;/option&gt;&#39;;

    if (!id) return;

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(id).onsuccess = (e) =&gt; {
        const p = e.target.result;
        if (p) {
            renderTable(p.entries || []);
            updateVillageDropdown(p.villages || []);
        }
    };
}

/* ================= RESET ================= */
function resetForm(clearVillage = true, skipDefaultRow = false) {
    document.getElementById(&#39;gatContainer&#39;).innerHTML = &quot;&quot;;

    if (clearVillage) {
        document.getElementById(&#39;activeVillageSelect&#39;).value = &quot;&quot;;
    }

    editingIndex = null;

    // ❌ prevent auto row during edit
    if (!skipDefaultRow) {
        addGatRow();
    }
}
  
  function importJSON(event) {
    const file = event.target.files[0];
    if (!file) return;

    const reader = new FileReader();

    reader.onload = function(e) {
        try {
            const data = JSON.parse(e.target.result);

            if (!data.name || !Array.isArray(data.entries)) {
                alert(&quot;Invalid file format&quot;);
                return;
            }

            const tx = db.transaction(&quot;projects&quot;, &quot;readwrite&quot;);
            const store = tx.objectStore(&quot;projects&quot;);

            let projectFound = false;

            store.openCursor().onsuccess = function(ev) {
                const cursor = ev.target.result;

                if (cursor) {
                    const existing = cursor.value;

                    // ✅ MATCH PROJECT BY NAME
                    if (existing.name === data.name) {
                        projectFound = true;

                        let existingEntries = existing.entries || [];
                        let newEntries = data.entries || [];

                        // 🔥 CREATE MAP FOR FAST DUPLICATE CHECK
                        const entryMap = new Map();

                        existingEntries.forEach(ent =&gt; {
                            const key = `${ent.village}__${ent.gat}`;
                            entryMap.set(key, ent);
                        });

                        // 🔥 MERGE LOGIC
                        newEntries.forEach(newEnt =&gt; {
                            const key = `${newEnt.village}__${newEnt.gat}`;

                            if (entryMap.has(key)) {
                                // 🔁 UPDATE EXISTING ENTRY
                                entryMap.set(key, newEnt);
                            } else {
                                // ➕ ADD NEW ENTRY
                                entryMap.set(key, newEnt);
                            }
                        });

                        // ✅ FINAL MERGED ARRAY
                        existing.entries = Array.from(entryMap.values());

                        // ✅ MERGE VILLAGES (NO DUPLICATES)
                        const villageSet = new Set([
                            ...(existing.villages || []),
                            ...(data.villages || [])
                        ]);
                        existing.villages = Array.from(villageSet);

                        // 💾 SAVE UPDATED PROJECT
                        cursor.update(existing).onsuccess = () =&gt; {
                            alert(&quot;Project merged successfully (duplicates avoided)&quot;);
                            refreshProjectList();
                            loadProjectData();
                        };

                        return;
                    }

                    cursor.continue();

                } else {
                    // 🆕 NO PROJECT FOUND → CREATE NEW
                    delete data.id;

                    store.add(data).onsuccess = () =&gt; {
                        alert(&quot;New project imported&quot;);
                        refreshProjectList();
                    };
                }
            };

        } catch (err) {
            console.error(err);
            alert(&quot;Error reading file&quot;);
        }
    };

    reader.readAsText(file);
}
  
 function exportJSON() {
    const projectId = parseInt(document.getElementById(&#39;projectSelect&#39;).value);
    if (!projectId) return alert(&quot;Select a project&quot;);

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(projectId).onsuccess = (e) =&gt; {
        const p = e.target.result;
        if (!p) return alert(&quot;No data&quot;);

        // ✅ Format date (DD-MM-YYYY)
        const now = new Date();
        const date = now.toLocaleDateString(&#39;en-GB&#39;).replace(/\//g, &#39;-&#39;);

        // ✅ Make project name file-safe
        const safeName = (p.name || &quot;Project&quot;)
            .replace(/[&lt;&gt;:&quot;/\\|?*]+/g, &#39;&#39;)   // remove invalid chars
            .replace(/\s+/g, &#39;_&#39;);           // replace spaces with underscore

        const fileName = `${date}_${safeName}.json`;

        const blob = new Blob([JSON.stringify(p, null, 2)], {
            type: &quot;application/json&quot;
        });

        const url = URL.createObjectURL(blob);

        const link = document.createElement(&quot;a&quot;);
        link.href = url;
        link.download = fileName;
        link.click();

        URL.revokeObjectURL(url);
    };
}
  
  function decodeHTML(html) {
    const txt = document.createElement(&quot;textarea&quot;);
    txt.innerHTML = html;
    return txt.value;
}
  
  
  function exportCSV() {
    const projectId = parseInt(document.getElementById(&#39;projectSelect&#39;).value);
    if (!projectId) return alert(&quot;Select project&quot;);

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(projectId).onsuccess = (e) =&gt; {
        const p = e.target.result;
        if (!p || !p.entries) return alert(&quot;No data&quot;);

        let csv = `Project Name,${p.name}\n\n`;

        // ✅ HEADER (EXACTLY AS REQUIRED)
        csv += decodeHTML(&quot;गाव,गट क्रमांक,मालकाचे नाव,जमिनीचा प्रकार,JMS स्थिती,मूल्यांकन स्थिती,कायदेशीर स्थिती,देय रक्कम, अदा केलेली रक्कम, बँक लोन भरणा रक्कम,ड्राफ्ट विक्री कागदपत्र,नोंदणी शुल्क,स्टॅम्प शुल्क,पेजिंग शुल्क,इतर खर्च,जमीन संपादन खर्च,देय दिनांक,आधार क्रमांक,PAN क्रमांक,बँक नाव,IFSC कोड,खाते क्रमांक,शेरा\n&quot;);

        p.entries.forEach(ent =&gt; {
            (ent.owners || []).forEach(o =&gt; {

                // ✅ SINGLE LINE PER ROW (VERY IMPORTANT)
                csv += `&quot;${ent.village}&quot;,&quot;${ent.gat}&quot;,&quot;${o.name}&quot;,&quot;${ent.category || &#39;&#39;}&quot;,&quot;${ent.jmsStatus || &#39;&#39;}&quot;,&quot;${ent.valuationStatus || &#39;&#39;}&quot;,&quot;${ent.legalStatus || &#39;&#39;}&quot;,${o.payable || 0},${o.paid || 0},${o.loanRepayment || 0},&quot;${o.draftDeed || &#39;&#39;}&quot;,${o.regFee || 0},${o.stampDuty || 0},${o.pagingFee || 0},${o.misc || 0},${o.laCost || 0},&quot;${o.paidDate || &#39;&#39;}&quot;,&quot;${o.aadhar || &#39;&#39;}&quot;,&quot;${o.pan || &#39;&#39;}&quot;,&quot;${o.bank || &#39;&#39;}&quot;,&quot;${o.ifsc || &#39;&#39;}&quot;,&quot;${o.account || &#39;&#39;}&quot;,&quot;${o.remarks || &#39;&#39;}&quot;\n`;

            });
        });

        // ✅ SAFE FILE NAME WITH DATE
        const now = new Date();
        const date = now.toLocaleDateString(&#39;en-GB&#39;).replace(/\//g, &#39;-&#39;);
        const safeName = p.name.replace(/[&lt;&gt;:&quot;/\\|?*]+/g, &#39;&#39;);

        const blob = new Blob([&quot;\uFEFF&quot; + csv], { type: &quot;text/csv;charset=utf-8;&quot; });
        const url = URL.createObjectURL(blob);

        const link = document.createElement(&quot;a&quot;);
        link.href = url;
        link.download = `${safeName}_${date}_LA_Detailed_Report.csv`;
        link.click();

        URL.revokeObjectURL(url);
    };
}
  
function generateMermaid() {

    function cleanText(txt) {
        if (!txt) return &#39;-&#39;;
        return String(txt)
            .replace(/&quot;/g, &quot;&#39;&quot;)
            .replace(/\n/g, &#39; &#39;)
            .replace(/&lt;/g, &#39;&amp;lt;&#39;)
            .replace(/&gt;/g, &#39;&amp;gt;&#39;);
    }

    const projectId = parseInt(document.getElementById(&#39;projectSelect&#39;).value);
    if (!projectId) return alert(&quot;Select project&quot;);

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(projectId).onsuccess = (e) =&gt; {

        const p = e.target.result;
        if (!p || !p.entries) return alert(&quot;No data&quot;);

        let diagram = &quot;flowchart TD\n&quot;;

        // ROOT NODE
        diagram += `P[&quot;🏗️ ${cleanText(p.name)}&quot;]\n`;

        const villageMap = {};
        const villageTotals = {};

        // ================= VILLAGE TOTALS =================
        p.entries.forEach(ent =&gt; {

            if (!villageTotals[ent.village]) {
                villageTotals[ent.village] = {
                    area: 0,
                    payable: 0,
                    paid: 0
                };
            }

            (ent.owners || []).forEach(o =&gt; {
                villageTotals[ent.village].area += (o.area || 0);
                villageTotals[ent.village].payable += (o.payable || 0);
                villageTotals[ent.village].paid += (o.paid || 0);
            });
        });

        // ================= BUILD DIAGRAM =================
        p.entries.forEach((ent, eIdx) =&gt; {

            const vName = cleanText(ent.village);
            const vKey = `V_${ent.village.replace(/\W/g, &#39;&#39;)}`;

            // ---- VILLAGE NODE ----
            if (!villageMap[ent.village]) {

                const v = villageTotals[ent.village];

                diagram += `P --&gt; ${vKey}[&quot;🏡 ${vName}&lt;br&gt;
Area: ${v.area.toFixed(2)}&lt;br&gt;
₹ Pay: ${v.payable.toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
₹ Paid: ${v.paid.toLocaleString(&#39;en-IN&#39;)}&quot;]\n`;

                villageMap[ent.village] = vKey;
            }

            // ---- GAT TOTALS ----
            let totalArea = 0, totalPayable = 0, totalPaid = 0;

            (ent.owners || []).forEach(o =&gt; {
                totalArea += (o.area || 0);
                totalPayable += (o.payable || 0);
                totalPaid += (o.paid || 0);
            });

            const balance = totalPayable - totalPaid;

            const gKey = `G${eIdx}_${cleanText(ent.gat).replace(/\W/g, &#39;&#39;)}`;

            // ---- GAT NODE ----
            diagram += `${villageMap[ent.village]} --&gt; ${gKey}[&quot;📍 Gat: ${cleanText(ent.gat)}&lt;br&gt;
Cat: ${cleanText(ent.category || &#39;-&#39;) }&lt;br&gt;
Area: ${totalArea.toFixed(2)}&lt;br&gt;
₹ Pay: ${totalPayable.toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
₹ Paid: ${totalPaid.toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
Bal: ₹${balance.toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;&lt;br&gt;

JMS: ${cleanText(ent.jmsStatus)}&lt;br&gt;
Val: ${cleanText(ent.valuationStatus)}&lt;br&gt;
Legal: ${cleanText(ent.legalStatus)}&quot;]\n`;

            // ---- OWNER NODES ----
            (ent.owners || []).forEach((o, oIdx) =&gt; {

                const oKey = `O${eIdx}_${oIdx}`;
                const bal = (o.payable || 0) - (o.paid || 0);

                const safeName = cleanText(o.name);

                diagram += `${gKey} --&gt; ${oKey}[&quot;👤 ${safeName}&lt;br&gt;
(${cleanText(o.type || &#39;Private&#39;)})&lt;br&gt;&lt;br&gt;

📐 Owned: ${(o.totalArea || 0).toFixed(2)}&lt;br&gt;
📏 Acq: ${(o.area || 0).toFixed(2)}&lt;br&gt;&lt;br&gt;

💰 Pay: ₹${(o.payable || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
💵 Paid: ₹${(o.paid || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
🏦 Loan: ₹${(o.loanRepayment || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
⚖️ Bal: ₹${bal.toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;&lt;br&gt;

📄 Draft: ${cleanText(o.draftDeed)}&lt;br&gt;
🧾 Reg: ₹${(o.regFee || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
🪙 Stamp: ₹${(o.stampDuty || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
📑 Paging: ₹${(o.pagingFee || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
📦 Misc: ₹${(o.misc || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
🏗️ LA Cost: ₹${(o.laCost || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;&lt;br&gt;

📅 Paid Dt: ${cleanText(o.paidDate)}&lt;br&gt;&lt;br&gt;

🆔 Aadhaar: ${cleanText(o.aadhar)}&lt;br&gt;
🪪 PAN: ${cleanText(o.pan)}&lt;br&gt;&lt;br&gt;

🏦 Bank: ${cleanText(o.bank)}&lt;br&gt;
🔢 IFSC: ${cleanText(o.ifsc)}&lt;br&gt;
💳 Acc: ${cleanText(o.account)}&lt;br&gt;&lt;br&gt;

📝 ${cleanText(o.remarks)}&quot;]\n`;

                // ---- CONDITIONAL COLOR ----
                if (!o.paid || o.paid === 0) {
                    diagram += `style ${oKey} fill:#fff3cd,stroke:#f39c12,stroke-width:2px\n`;
                }
            });
        });

        // ================= RENDER =================
        const container = document.getElementById(&quot;mermaidChart&quot;);
        container.innerHTML = diagram;

        try {
            mermaid.init(undefined, container);
        } catch (err) {
            console.error(err);
            alert(&quot;Mermaid rendering error&quot;);
        }
    };
}
  
 function exportMermaidA2() {
    const svg = document.querySelector(&quot;#mermaidChart svg&quot;);
    if (!svg) {
        alert(&quot;Generate diagram first&quot;);
        return;
    }

    // Clone original SVG
    const clone = svg.cloneNode(true);

    // Get actual diagram size
    const bbox = svg.getBBox();

    // A2 Landscape (px)
    const A2_WIDTH = 594 * 3.78;   // ≈ 2244 px
    const A2_HEIGHT = 420 * 3.78;  // ≈ 1587 px

    // Calculate scale (fit inside A2)
    const scaleX = A2_WIDTH / bbox.width;
    const scaleY = A2_HEIGHT / bbox.height;
    const scale = Math.min(scaleX, scaleY);

    const scaledWidth = bbox.width * scale;
    const scaledHeight = bbox.height * scale;

    // Centering offsets (to fully utilize page)
    const offsetX = (A2_WIDTH - scaledWidth) / 2;
    const offsetY = (A2_HEIGHT - scaledHeight) / 2;

    // Set proper viewBox (VERY IMPORTANT)
    clone.setAttribute(
        &quot;viewBox&quot;,
        `${bbox.x - offsetX/scale} ${bbox.y - offsetY/scale} ${A2_WIDTH/scale} ${A2_HEIGHT/scale}`
    );

    clone.setAttribute(&quot;width&quot;, A2_WIDTH);
    clone.setAttribute(&quot;height&quot;, A2_HEIGHT);

    // Optional: Improve text readability
    clone.style.background = &quot;white&quot;;

    // Serialize SVG
    const svgData = new XMLSerializer().serializeToString(clone);
    const blob = new Blob([svgData], { type: &quot;image/svg+xml;charset=utf-8&quot; });

    const url = URL.createObjectURL(blob);

    // Safe filename with date
    const now = new Date();
    const date = now.toLocaleDateString(&#39;en-GB&#39;).replace(/\//g, &#39;-&#39;);

    const link = document.createElement(&quot;a&quot;);
    link.href = url;
    link.download = `Land_Acquisition_A2_${date}.svg`;
    link.click();

    URL.revokeObjectURL(url);
}
  
  function generateVillageSummary() {
    const projectId = parseInt(document.getElementById(&#39;projectSelect&#39;).value);
    if (!projectId) return alert(&quot;Select project&quot;);

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(projectId).onsuccess = (e) =&gt; {
        const p = e.target.result;
        if (!p || !p.entries) return alert(&quot;No data&quot;);

        const summary = {};

        p.entries.forEach(ent =&gt; {
            const village = ent.village;
            const category = ent.category || &quot;Class-1&quot;;

            if (!summary[village]) {
                summary[village] = {
                    &quot;Class-1&quot;: 0,
                    &quot;Class-2&quot;: 0,
                    &quot;PESA&quot;: 0
                };
            }

            // Sum acquired area (owner area)
            (ent.owners || []).forEach(o =&gt; {
                summary[village][category] += (o.area || 0);
            });
        });

        // Render table
        const tbody = document.getElementById(&#39;villageSummaryBody&#39;);
        tbody.innerHTML = &quot;&quot;;

        Object.keys(summary).forEach(village =&gt; {
            const v = summary[village];

            const total = v[&quot;Class-1&quot;] + v[&quot;Class-2&quot;] + v[&quot;PESA&quot;];

            tbody.innerHTML += `
                &lt;tr&gt;
                    &lt;td&gt;&lt;b&gt;${village}&lt;/b&gt;&lt;/td&gt;
                    &lt;td&gt;${v[&quot;Class-1&quot;].toFixed(4)}&lt;/td&gt;
                    &lt;td&gt;${v[&quot;Class-2&quot;].toFixed(4)}&lt;/td&gt;
                    &lt;td&gt;${v[&quot;PESA&quot;].toFixed(4)}&lt;/td&gt;
                    &lt;td&gt;&lt;b&gt;${total.toFixed(4)}&lt;/b&gt;&lt;/td&gt;
                &lt;/tr&gt;
            `;
        });
    };
}
  
  function generateVillageOnlyMermaid() {

    function cleanText(txt) {
        if (!txt) return &#39;-&#39;;
        return String(txt)
            .replace(/&quot;/g, &quot;&#39;&quot;)
            .replace(/\n/g, &#39; &#39;)
            .replace(/&lt;/g, &#39;&amp;lt;&#39;)
            .replace(/&gt;/g, &#39;&amp;gt;&#39;);
    }

    const projectId = parseInt(document.getElementById(&#39;projectSelect&#39;).value);
    if (!projectId) return alert(&quot;Select project&quot;);

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(projectId).onsuccess = (e) =&gt; {

        const p = e.target.result;
        if (!p || !p.entries) return alert(&quot;No data&quot;);

        let diagram = &quot;flowchart TD\n&quot;; // horizontal looks better here

        // ROOT
        diagram += `P[&quot;🏗️ ${cleanText(p.name)}&quot;]\n`;

        const villageTotals = {};

        // ---- CALCULATE VILLAGE TOTALS ----
        p.entries.forEach(ent =&gt; {

            if (!villageTotals[ent.village]) {
                villageTotals[ent.village] = {
                    area: 0,
                    payable: 0,
                    paid: 0,
                    gats: 0,
                    owners: 0
                };
            }

            villageTotals[ent.village].gats += 1;

            (ent.owners || []).forEach(o =&gt; {
                villageTotals[ent.village].area += (o.area || 0);
                villageTotals[ent.village].payable += (o.payable || 0);
                villageTotals[ent.village].paid += (o.paid || 0);
                villageTotals[ent.village].owners += 1;
            });
        });

        // ---- CREATE VILLAGE NODES ----
        Object.keys(villageTotals).forEach((village, idx) =&gt; {

            const v = villageTotals[village];
            const vKey = `VONLY_${idx}`;

            diagram += `P --&gt; ${vKey}[&quot;🏡 ${cleanText(village)}&lt;br&gt;&lt;br&gt;
📍 Gats: ${v.gats}&lt;br&gt;
👤 Owners: ${v.owners}&lt;br&gt;&lt;br&gt;

📐 Area: ${v.area.toFixed(2)}&lt;br&gt;
💰 Payable: ₹${v.payable.toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
💵 Paid: ₹${v.paid.toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
⚖️ Balance: ₹${(v.payable - v.paid).toLocaleString(&#39;en-IN&#39;)}&quot;]\n`;

            // Optional color logic
            if (v.paid === 0) {
                diagram += `style ${vKey} fill:#fff3cd,stroke:#f39c12,stroke-width:2px\n`;
            }
        });

        // ---- RENDER ----
        const container = document.getElementById(&quot;villageOnlyChart&quot;);
        container.innerHTML = diagram;

        try {
            mermaid.init(undefined, container);
        } catch (err) {
            console.error(err);
            alert(&quot;Mermaid rendering error&quot;);
        }
    };
}
  
  function generateAllVillageCharts() {

    function cleanText(txt) {
        if (!txt) return &#39;-&#39;;
        return String(txt)
            .replace(/&quot;/g, &quot;&#39;&quot;)
            .replace(/\n/g, &#39; &#39;)
            .replace(/&lt;/g, &#39;&amp;lt;&#39;)
            .replace(/&gt;/g, &#39;&amp;gt;&#39;);
    }

    const projectId = parseInt(document.getElementById(&#39;projectSelect&#39;).value);
    if (!projectId) return alert(&quot;Select project&quot;);

    db.transaction(&quot;projects&quot;).objectStore(&quot;projects&quot;).get(projectId).onsuccess = (e) =&gt; {

        const p = e.target.result;
        if (!p || !p.entries) return alert(&quot;No data&quot;);

        const container = document.getElementById(&quot;allVillageCharts&quot;);
        container.innerHTML = &quot;&quot;;

        const villages = [...new Set(p.entries.map(e =&gt; e.village))];

        villages.forEach((village, vIdx) =&gt; {

            let diagram = &quot;flowchart TD\n&quot;;

            const vKey = `V_${vIdx}`;
            diagram += `${vKey}[&quot;🏡 ${cleanText(village)}&quot;]\n`;

            // FILTER ENTRIES OF THIS VILLAGE
            const villageEntries = p.entries.filter(e =&gt; e.village === village);

            villageEntries.forEach((ent, eIdx) =&gt; {

                const gKey = `G_${vIdx}_${eIdx}`;

                diagram += `${vKey} --&gt; ${gKey}[&quot;📍 Gat: ${cleanText(ent.gat)}&lt;br&gt;
Cat: ${cleanText(ent.category)}&lt;br&gt;
JMS: ${cleanText(ent.jmsStatus)}&lt;br&gt;
Val: ${cleanText(ent.valuationStatus)}&lt;br&gt;
Legal: ${cleanText(ent.legalStatus)}&quot;]\n`;

                (ent.owners || []).forEach((o, oIdx) =&gt; {

                    const oKey = `O_${vIdx}_${eIdx}_${oIdx}`;
                    const bal = (o.payable || 0) - (o.paid || 0);

                    diagram += `${gKey} --&gt; ${oKey}[&quot;👤 ${cleanText(o.name)}&lt;br&gt;
📐 ${(o.totalArea || 0).toFixed(2)} | 📏 ${(o.area || 0).toFixed(2)}&lt;br&gt;
💰 ₹${(o.payable || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
💵 ₹${(o.paid || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
🏦 Loan: ₹${(o.loanRepayment || 0).toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;
⚖️ ₹${bal.toLocaleString(&#39;en-IN&#39;)}&lt;br&gt;&lt;br&gt;

📄 ${cleanText(o.draftDeed)}&lt;br&gt;
📅 ${cleanText(o.paidDate)}&lt;br&gt;
🆔 ${cleanText(o.aadhar)}&lt;br&gt;
🏦 ${cleanText(o.bank)}&quot;]\n`;

                    // Highlight unpaid
                    if (!o.paid || o.paid === 0) {
                        diagram += `style ${oKey} fill:#fff3cd,stroke:#f39c12,stroke-width:2px\n`;
                    }
                });
            });

            // CREATE BLOCK PER VILLAGE
            const div = document.createElement(&quot;div&quot;);
            div.className = &quot;card&quot;;
            div.style.marginBottom = &quot;20px&quot;;

            div.innerHTML = `
                &lt;h4&gt;Village: ${village}&lt;/h4&gt;
                &lt;div class=&quot;mermaid&quot;&gt;${diagram}&lt;/div&gt;
            `;

            container.appendChild(div);
        });

        try {
            mermaid.init(undefined, document.querySelectorAll(&quot;#allVillageCharts .mermaid&quot;));
        } catch (err) {
            console.error(err);
            alert(&quot;Mermaid rendering error&quot;);
        }
    };
}
  
 async function exportAllVillageChartsSVG() {

    const charts = document.querySelectorAll(&quot;#allVillageCharts svg&quot;);

    if (!charts.length) {
        alert(&quot;Generate charts first&quot;);
        return;
    }

    const now = new Date();
    const date = now.toLocaleDateString(&#39;en-GB&#39;).replace(/\//g, &#39;-&#39;);

    for (let i = 0; i &lt; charts.length; i++) {

        const svg = charts[i];
        const clone = svg.cloneNode(true);

        // White background
        clone.style.background = &quot;white&quot;;

        const svgData = new XMLSerializer().serializeToString(clone);
        const blob = new Blob([svgData], { type: &quot;image/svg+xml;charset=utf-8&quot; });

        const url = URL.createObjectURL(blob);

        const link = document.createElement(&quot;a&quot;);
        link.href = url;
        link.download = `Village_Chart_${i + 1}_${date}.svg`;

        document.body.appendChild(link); // required for some browsers
        link.click();
        document.body.removeChild(link);

        // Cleanup
        setTimeout(() =&gt; URL.revokeObjectURL(url), 1000);

        // 🔥 IMPORTANT: Delay to allow download
        await new Promise(resolve =&gt; setTimeout(resolve, 500));
    }
}
  
function exportVillageOnlySVG() {

    const svg = document.querySelector(&quot;#villageOnlyChart svg&quot;);

    if (!svg) {
        alert(&quot;Generate village chart first&quot;);
        return;
    }

    const clone = svg.cloneNode(true);

    // ✅ Add white background (proper SVG way)
    const bg = document.createElementNS(&quot;http://www.w3.org/2000/svg&quot;, &quot;rect&quot;);
    bg.setAttribute(&quot;width&quot;, &quot;100%&quot;);
    bg.setAttribute(&quot;height&quot;, &quot;100%&quot;);
    bg.setAttribute(&quot;fill&quot;, &quot;white&quot;);

    clone.insertBefore(bg, clone.firstChild);

    // ✅ FIX: Only apply computed styles where attributes are missing
    const elements = clone.querySelectorAll(&quot;*&quot;);

    elements.forEach(el =&gt; {
        const computed = window.getComputedStyle(el);

        // 🔥 DO NOT override existing fill/stroke
        if (!el.getAttribute(&quot;fill&quot;)) {
            el.setAttribute(&quot;fill&quot;, computed.fill);
        }

        if (!el.getAttribute(&quot;stroke&quot;)) {
            el.setAttribute(&quot;stroke&quot;, computed.stroke);
        }

        if (!el.getAttribute(&quot;stroke-width&quot;)) {
            el.setAttribute(&quot;stroke-width&quot;, computed.strokeWidth);
        }

        // Fonts (safe to apply)
        el.setAttribute(&quot;font-size&quot;, computed.fontSize);
        el.setAttribute(&quot;font-family&quot;, computed.fontFamily);
        el.setAttribute(&quot;font-weight&quot;, computed.fontWeight);
    });

    // Serialize
    let svgData = new XMLSerializer().serializeToString(clone);

    // Fix HTML issues
    svgData = svgData
        .replace(/&lt;br&gt;/g, &quot;&lt;br/&gt;&quot;)
        .replace(/&amp;nbsp;/g, &quot; &quot;);

    const blob = new Blob([svgData], { type: &quot;image/svg+xml;charset=utf-8&quot; });
    const url = URL.createObjectURL(blob);

    // File name
    const now = new Date();
    const date = now.toLocaleDateString(&#39;en-GB&#39;).replace(/\//g, &#39;-&#39;);

    const link = document.createElement(&quot;a&quot;);
    link.href = url;
    link.download = `Village_Summary_${date}.svg`;
    link.click();

    URL.revokeObjectURL(url);
}
  function decodeHTML(html) {
    const txt = document.createElement(&quot;textarea&quot;);
    txt.innerHTML = html;
    return txt.value;
}
&lt;/script&gt;
&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/04/land-acquisition-data-entry.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-920994611213108038</guid><pubDate>Fri, 27 Mar 2026 18:06:00 +0000</pubDate><atom:updated>2026-06-23T14:08:02.711+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Software</category><title>PEB section Estimation calculator </title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;PEB Structural member Estimation&lt;/title&gt;
    
    &lt;script type=&quot;text/x-mathjax-config&quot;&gt;
      MathJax.Hub.Config({
        tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]], processEscapes: true}
      });
    &lt;/script&gt;
    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-AMS-MML_HTMLorMML&quot;&gt;&lt;/script&gt;

    &lt;style&gt;
        body { font-family: &#39;Segoe UI&#39;, Arial, sans-serif; background-color: #f0f2f5; padding: 2px; color: #333; }
        .container { max-width: 1300px; margin: auto; background: white; padding: 3px; border-radius: 15px; box-shadow: 0 10px 30px rgba(0,0,0,0.1); }
        h2 { color: #1a3a5a; border-left: 5px solid #3498db; padding-left: 15px; }
        .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 25px; background: #f8f9fa; padding: 20px; border-radius: 10px; }
        .input-group { display: flex; flex-direction: column; }
        label { font-weight: 600; font-size: 0.85em; margin-bottom: 5px; color: #555; }
        input, select { padding: 12px; border: 1px solid #ccc; border-radius: 6px; }
        button { width: 100%; padding: 15px; background: #2c3e50; color: white; border: none; border-radius: 6px; font-size: 1.1em; font-weight: bold; cursor: pointer; transition: 0.3s; margin-top: 10px; }
        button:hover { background: #34495e; }
        .results { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 30px; }
        .card { background: white; border: 1px solid #e1e4e8; padding: 20px; border-radius: 10px; }
        .card h3 { margin-top: 0; font-size: 0.9em; color: #3498db; text-transform: uppercase; border-bottom: 1px solid #eee; padding-bottom: 5px; }
        table { width: 100%; border-collapse: collapse; }
        td { padding: 8px 0; border-bottom: 1px solid #eee; font-size: 0.95em; }
        td:last-child { text-align: right; font-weight: bold; color: #2c3e50; }
        .full-width { grid-column: span 2; }
        .highlight { color: #e74c3c; font-weight: bold; }
      h1, h2 {
    color: #1a3a5a;
}
h2 {
    border-left: 5px solid #3498db;
    padding-left: 10px;
}
p {
    margin: 10px 0;
}
ul {
    margin-left: 20px;
}
.code {
    background: #f8f9fa;
    padding: 10px;
    border-left: 4px solid #3498db;
    font-family: monospace;
}
.highlight {
    color: #e74c3c;
    font-weight: bold;
}
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;container&quot;&gt;
    &lt;h2&gt;PEB tentative section Estimation&lt;/h2&gt;
    
    &lt;div class=&quot;grid&quot;&gt;
        &lt;div class=&quot;input-group&quot;&gt;&lt;label&gt;Span ($L$) [m]&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;span&quot; value=&quot;30&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;input-group&quot;&gt;&lt;label&gt;Bay Spacing [m]&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;bay&quot; value=&quot;8&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;input-group&quot;&gt;&lt;label&gt;Eave Height [m]&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;height&quot; value=&quot;7&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;input-group&quot;&gt;
            &lt;label&gt;Base Connection&lt;/label&gt;
            &lt;select id=&quot;baseType&quot;&gt;
                &lt;option value=&quot;pinned&quot;&gt;Pinned (Standard)&lt;/option&gt;
                &lt;option value=&quot;fixed&quot;&gt;Fixed (Rigid)&lt;/option&gt;
            &lt;/select&gt;
        &lt;/div&gt;
        &lt;div class=&quot;input-group&quot;&gt;
            &lt;label&gt;Wind Speed ($V_b$)&lt;/label&gt;
            &lt;select id=&quot;wind&quot;&gt;
                &lt;option value=&quot;33&quot;&gt;33 m/s (Low)&lt;/option&gt;
                &lt;option value=&quot;44&quot; selected&gt;44 m/s (Medium)&lt;/option&gt;
                &lt;option value=&quot;50&quot;&gt;50 m/s (High/Coastal)&lt;/option&gt;
            &lt;/select&gt;
        &lt;/div&gt;
        &lt;button onclick=&quot;runCalculations()&quot;&gt;Generate Design &amp; Formulas&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class=&quot;results&quot; id=&quot;output&quot; style=&quot;display:none;&quot;&gt;
        &lt;div class=&quot;card&quot;&gt;
            &lt;h3&gt;Primary Geometry&lt;/h3&gt;
            &lt;table&gt;
                &lt;tr&gt;&lt;td&gt;Optimum Max Depth&lt;/td&gt;&lt;td id=&quot;res-dmax&quot;&gt;--&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;Min Web Thickness&lt;/td&gt;&lt;td id=&quot;res-tw&quot;&gt;--&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;Flange Width&lt;/td&gt;&lt;td id=&quot;res-fw&quot;&gt;--&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;Deflection Limit ($L/180$)&lt;/td&gt;&lt;td id=&quot;res-def&quot;&gt;--&lt;/td&gt;&lt;/tr&gt;
            &lt;/table&gt;
        &lt;/div&gt;

        &lt;div class=&quot;card&quot;&gt;
            &lt;h3&gt;Anchor &amp; Shear Key&lt;/h3&gt;
            &lt;table&gt;
                &lt;tr&gt;&lt;td&gt;Anchor Bolts&lt;/td&gt;&lt;td id=&quot;res-bolt&quot;&gt;--&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;Embedment ($15 \times d$)&lt;/td&gt;&lt;td id=&quot;res-embed&quot;&gt;--&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;Shear Key Req.&lt;/td&gt;&lt;td id=&quot;res-skey&quot;&gt;--&lt;/td&gt;&lt;/tr&gt;
                &lt;tr&gt;&lt;td&gt;Key Size (Approx)&lt;/td&gt;&lt;td id=&quot;res-skey-size&quot;&gt;--&lt;/td&gt;&lt;/tr&gt;
            &lt;/table&gt;
        &lt;/div&gt;

        &lt;div class=&quot;card full-width&quot;&gt;
            &lt;h3&gt;Design Logic &amp; Weight&lt;/h3&gt;
            &lt;div id=&quot;math-output&quot;&gt;&lt;/div&gt;
            &lt;p style=&quot;text-align:right;&quot;&gt;&lt;strong&gt;Est. Steel: &lt;span id=&quot;res-total-mt&quot;&gt;&lt;/span&gt; MT/bay&lt;/strong&gt;&lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
  
  &lt;div class=&quot;container&quot;&gt;

&lt;h1&gt;PEB Structural Member Estimation Tool – Technical Explanation&lt;/h1&gt;

&lt;p&gt;
This tool is developed for &lt;strong&gt;Pre-Engineered Building (PEB)&lt;/strong&gt; preliminary design. It provides
quick and reliable estimates of structural member sizes, anchor systems, and steel weight based on
standard engineering thumb rules and practical industry experience.
&lt;/p&gt;

&lt;h2&gt;1. Objective of the Tool&lt;/h2&gt;
&lt;p&gt;
The primary objective is to assist engineers in obtaining:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Preliminary rafter depth and plate sizes&lt;/li&gt;
&lt;li&gt;Steel quantity estimation&lt;/li&gt;
&lt;li&gt;Anchor bolt requirements&lt;/li&gt;
&lt;li&gt;Shear key necessity check&lt;/li&gt;
&lt;li&gt;Basic design validation using engineering logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;2. Input Parameters&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Span (L):&lt;/strong&gt; Distance between columns&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bay Spacing (B):&lt;/strong&gt; Distance between frames&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eave Height (H):&lt;/strong&gt; Height at column top&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Base Connection:&lt;/strong&gt; Pinned or Fixed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wind Speed (Vb):&lt;/strong&gt; Governing lateral load parameter&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;3. Primary Member Design Logic&lt;/h2&gt;

&lt;h3&gt;3.1 Rafter Depth Estimation&lt;/h3&gt;
&lt;p&gt;
The tool uses a widely accepted optimization ratio:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
d ≈ L / 28
&lt;/div&gt;

&lt;p&gt;
Where:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;d = depth of rafter (mm)&lt;/li&gt;
&lt;li&gt;L = span (mm)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This ensures:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Efficient bending resistance&lt;/li&gt;
&lt;li&gt;Economical steel usage&lt;/li&gt;
&lt;li&gt;Compliance with deflection limits&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;3.2 Web Thickness&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
tw = d / 150 (minimum 6 mm)
&lt;/div&gt;

&lt;p&gt;
This criterion ensures:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Shear capacity adequacy&lt;/li&gt;
&lt;li&gt;Prevention of web buckling&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;3.3 Flange Width&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
bf = d / 5 (minimum 150 mm)
&lt;/div&gt;

&lt;p&gt;
Flange width governs:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bending strength&lt;/li&gt;
&lt;li&gt;Lateral torsional stability&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;3.4 Deflection Check&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Allowable Deflection = L / 180
&lt;/div&gt;

&lt;p&gt;
This is a standard serviceability limit used in industrial structures.
&lt;/p&gt;

&lt;h2&gt;4. Steel Weight Estimation&lt;/h2&gt;

&lt;p&gt;
The steel consumption is estimated using empirical relationships:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
kg/m² = 25 + (0.5 × L) + Wind Factor
&lt;/div&gt;

&lt;p&gt;
Where:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Base value = 25 kg/m² (light structure)&lt;/li&gt;
&lt;li&gt;Span effect increases steel&lt;/li&gt;
&lt;li&gt;Wind factor adds 10 kg/m² for high wind zones&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;code&quot;&gt;
Total Steel (MT) = (kg/m² × L × B) / 1000
&lt;/div&gt;

&lt;p&gt;
This gives steel per bay, useful for:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cost estimation&lt;/li&gt;
&lt;li&gt;Feasibility studies&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;5. Anchor Bolt Design Logic&lt;/h2&gt;

&lt;h3&gt;Bolt Diameter Selection&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
If L &gt; 30 m → M30 bolts  
Else → M24 bolts
&lt;/div&gt;

&lt;h3&gt;Bolt Quantity&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Pinned Base → 4 bolts  
Fixed Base → 8 bolts
&lt;/div&gt;

&lt;h3&gt;Embedment Depth&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Embedment = 15 × Bolt Diameter
&lt;/div&gt;

&lt;p&gt;
This ensures proper anchorage and pull-out resistance.
&lt;/p&gt;

&lt;h2&gt;6. Shear Key Requirement&lt;/h2&gt;

&lt;p&gt;
Shear key necessity is checked using friction vs shear condition:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
If Vu &gt; μ × Pu → Shear Key Required
&lt;/div&gt;

&lt;p&gt;
Simplified logic used in the tool:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High wind (≥ 44 m/s) OR large span (&gt; 35 m) → Shear key required&lt;/li&gt;
&lt;li&gt;Otherwise friction is sufficient&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Typical Shear Key Sizes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ISMC 150 channel&lt;/li&gt;
&lt;li&gt;100 × 100 box section&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;7. Role of MathJax&lt;/h2&gt;

&lt;p&gt;
The tool integrates &lt;strong&gt;MathJax&lt;/strong&gt; to dynamically render engineering equations such as:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Depth optimization formulas&lt;/li&gt;
&lt;li&gt;Weight calculations&lt;/li&gt;
&lt;li&gt;Design inequalities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This improves readability and provides a professional engineering interface.
&lt;/p&gt;

&lt;h2&gt;8. Engineering Assumptions&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Preliminary design only (not final design)&lt;/li&gt;
&lt;li&gt;Uniform loading conditions&lt;/li&gt;
&lt;li&gt;Standard material properties&lt;/li&gt;
&lt;li&gt;Typical industrial building configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;9. Limitations&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Does not replace detailed structural analysis&lt;/li&gt;
&lt;li&gt;No seismic load consideration&lt;/li&gt;
&lt;li&gt;No connection design verification&lt;/li&gt;
&lt;li&gt;No code-specific checks (IS 800, MBMA, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;10. Conclusion&lt;/h2&gt;

&lt;p&gt;
This PEB estimation tool serves as a &lt;span class=&quot;highlight&quot;&gt;fast and practical design assistant&lt;/span&gt; 
for structural engineers. It bridges the gap between conceptual design and detailed analysis,
helping engineers make informed decisions quickly.
&lt;/p&gt;

&lt;p&gt;
For final design, it is recommended to validate results using detailed structural analysis software
and relevant design codes.
&lt;/p&gt;

&lt;/div&gt;

&lt;script&gt;
function runCalculations() {
    const L = parseFloat(document.getElementById(&#39;span&#39;).value);
    const B = parseFloat(document.getElementById(&#39;bay&#39;).value);
    const H = parseFloat(document.getElementById(&#39;height&#39;).value);
    const Vb = parseFloat(document.getElementById(&#39;wind&#39;).value);
    const base = document.getElementById(&#39;baseType&#39;).value;

    // Calculations
    let d_max = Math.ceil((L * 1000 / 28) / 50) * 50;
    let tw = Math.ceil(d_max / 150); if(tw &lt; 6) tw = 6;
    let fw = Math.ceil((d_max/5)/25)*25; if(fw &lt; 150) fw = 150;
    
    // Weight logic
    let kg_m2 = 25 + (L * 0.5) + (Vb &gt; 44 ? 10 : 0);
    let total_mt = (kg_m2 * L * B) / 1000;

    // Anchor &amp; Shear logic
    let bolt_dia = L &gt; 30 ? 30 : 24;
    let bolt_qty = base === &#39;fixed&#39; ? 8 : 4;
    let shear_key_req = (Vb &gt;= 44 || L &gt; 35) ? &quot;YES&quot; : &quot;NO (Friction OK)&quot;;
    let skey_size = shear_key_req === &quot;YES&quot; ? &quot;ISMC 150 or 100x100 Box&quot; : &quot;N/A&quot;;

    // Results display
    document.getElementById(&#39;output&#39;).style.display = &#39;grid&#39;;
    document.getElementById(&#39;res-dmax&#39;).innerText = d_max + &quot; mm&quot;;
    document.getElementById(&#39;res-tw&#39;).innerText = tw + &quot; mm&quot;;
    document.getElementById(&#39;res-fw&#39;).innerText = fw + &quot; mm&quot;;
    document.getElementById(&#39;res-def&#39;).innerText = (L*1000/180).toFixed(1) + &quot; mm&quot;;
    
    document.getElementById(&#39;res-bolt&#39;).innerText = bolt_qty + &quot; Nos M&quot; + bolt_dia;
    document.getElementById(&#39;res-embed&#39;).innerText = (bolt_dia * 15) + &quot; mm&quot;;
    document.getElementById(&#39;res-skey&#39;).innerText = shear_key_req;
    document.getElementById(&#39;res-skey-size&#39;).innerText = skey_size;
    document.getElementById(&#39;res-total-mt&#39;).innerText = total_mt.toFixed(2);

    // Dynamic MathJax Rendering
    const mathDiv = document.getElementById(&#39;math-output&#39;);
    mathDiv.innerHTML = `
        &lt;p&gt;Using optimization ratio $d \\approx L/28$, the calculated depth is $${d_max}\\text{ mm}$.&lt;/p&gt;
        &lt;p&gt;The estimated steel consumption is calculated as: 
        $$\\text{Weight} = (${kg_m2.toFixed(1)}\\text{ kg/m}^2) \\times (L \\times B)$$&lt;/p&gt;
        &lt;p&gt;Shear capacity check: If $V_u &gt; \\mu \\cdot P_u$, then a Shear Key is required.&lt;/p&gt;
    `;

    // Re-run MathJax to process new dynamic content
    MathJax.Hub.Queue([&quot;Typeset&quot;, MathJax.Hub, mathDiv]);
}
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;
&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/03/peb-section-estimation-calculator.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-3162939310620119729</guid><pubDate>Sat, 21 Mar 2026 09:06:10 +0000</pubDate><atom:updated>2026-04-06T12:18:17.097+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><title>Letter correspondence</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Letter Correspondence Manager&lt;/title&gt;
    &lt;script src=&quot;https://cdn.tailwindcss.com&quot;&gt;&lt;/script&gt;
    &lt;style&gt;
        body { background-color: #f3f4f6; padding: 1rem; font-family: sans-serif; scroll-behavior: smooth; }
        @media (min-width: 768px) { body { padding: 2.5rem; } }
        .max-w-5xl { max-width: 64rem; margin: 0 auto; background-color: white; padding: 1.5rem; border-radius: 0.75rem; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); }
        h2 { font-size: 1.5rem; font-weight: 700; margin-bottom: 1.5rem; color: #1f2937; border-bottom: 1px solid #e5e7eb; padding-bottom: 1rem; }
        label { display: block; font-size: 0.875rem; font-weight: 600; color: #374151; margin-bottom: 0.25rem; }
        form { display: grid; grid-template-columns: 1fr; gap: 1.25rem; }
        @media (min-width: 768px) { form { grid-template-columns: repeat(2, minmax(0, 1fr)); } .md\:col-span-2 { grid-column: span 2 / span 2; } }
        input, select, textarea { width: 100%; padding: 0.625rem; border: 1px solid #d1d5db; border-radius: 0.5rem; outline: none; }
        input:focus, select:focus, textarea:focus { ring: 2px solid #3b82f6; border-color: #3b82f6; }
        #action { border-color: #93c5fd; background-color: #eff6ff; color: #2563eb; font-weight: 500; }
        button, .cursor-pointer { padding: 0.75rem 1.5rem; border-radius: 0.5rem; font-weight: 700; cursor: pointer; border: none; transition: background 0.2s; text-align: center; }
        #submitBtn { background-color: #2563eb; color: white; flex: 1; }
        .bg-yellow-600 { background-color: #ca8a04; color: white; }
        .bg-green-600 { background-color: #16a34a; color: white; }
        .bg-orange-500 { background-color: #f97316; color: white; }
        .bg-gray-600 { background-color: #4b5563; color: white; }
        
        /* --- HORIZONTAL SCROLL STYLING --- */
        .table-container { 
            width: 100%; 
            overflow-x: auto; /* Enables the scrollbar */
            border: 1px solid #e5e7eb;
            border-radius: 0.5rem;
            background: white;
        }

        table { 
            width: 100%; 
            min-width: 1000px; /* Force the table to be wide enough to show all columns */
            border-collapse: collapse; 
            font-size: 0.875rem; 
            text-align: left; 
        }
        
        /* Custom Scrollbar Styling (Optional) */
        .table-container::-webkit-scrollbar { height: 8px; }
        .table-container::-webkit-scrollbar-track { background: #f1f1f1; }
        .table-container::-webkit-scrollbar-thumb { background: #888; border-radius: 10px; }
        .table-container::-webkit-scrollbar-thumb:hover { background: #555; }

        th, td { padding: 0.75rem; border: 1px solid #e5e7eb; white-space: nowrap; } /* Prevent text wrapping */
        .hidden { display: none; }
      }
h1, h2 {
    color: #1a3a5a;
}
h2 {
    border-left: 5px solid #3498db;
    padding-left: 10px;
}
ul {
    margin-left: 20px;
}
.code {
    background: #f8f9fa;
    padding: 10px;
    border-left: 4px solid #3498db;
    font-family: monospace;
}
.highlight {
    color: #e74c3c;
    font-weight: bold;
}
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class=&quot;max-w-5xl mx-auto&quot;&gt;
        &lt;h2&gt;Letter Correspondence Entry&lt;/h2&gt;
        
        &lt;form id=&quot;letterForm&quot;&gt;
            &lt;div&gt;
                &lt;label&gt;Sr. No&lt;/label&gt;
                &lt;input type=&quot;number&quot; id=&quot;sr&quot; required&gt;
            &lt;/div&gt;
            &lt;div&gt;
                &lt;label&gt;Subject&lt;/label&gt;
                &lt;input type=&quot;text&quot; id=&quot;subj&quot; required&gt;
            &lt;/div&gt;
            &lt;div&gt;
                &lt;label&gt;Letter Date&lt;/label&gt;
                &lt;input type=&quot;date&quot; id=&quot;l_date&quot;&gt;
            &lt;/div&gt;
            &lt;div&gt;
                &lt;label&gt;Letter Number&lt;/label&gt;
                &lt;input type=&quot;text&quot; id=&quot;l_num&quot;&gt;
            &lt;/div&gt;
           &lt;div&gt;
    &lt;label&gt;Letter Received Date&lt;/label&gt;
    &lt;input type=&quot;date&quot; id=&quot;r_date&quot;&gt;
&lt;/div&gt;
&lt;div&gt;
    &lt;label&gt;Letter Received Number&lt;/label&gt;
    &lt;input type=&quot;text&quot; id=&quot;r_num&quot;&gt;
&lt;/div&gt;
            &lt;div&gt;
                &lt;label class=&quot;text-blue-600&quot;&gt;Action Taken&lt;/label&gt;
                &lt;select id=&quot;action&quot; required&gt;
                    &lt;option value=&quot;&quot; disabled selected&gt;-- Select Status --&lt;/option&gt;
                    &lt;option value=&quot;Forwarded&quot;&gt;1) Forwarded&lt;/option&gt;
                    &lt;option value=&quot;Reverted&quot;&gt;2) Reverted&lt;/option&gt;
                    &lt;option value=&quot;Filed&quot;&gt;3) Filed&lt;/option&gt;
                    &lt;option value=&quot;Action Yet to be taken&quot;&gt;4) Action Yet to be taken&lt;/option&gt;
                &lt;/select&gt;
            &lt;/div&gt;
            &lt;div&gt;
                &lt;label&gt;Reply Date&lt;/label&gt;
                &lt;input type=&quot;date&quot; id=&quot;rep_date&quot;&gt;
            &lt;/div&gt;
            &lt;div class=&quot;md:col-span-2&quot;&gt;
                &lt;label&gt;Remarks&lt;/label&gt;
                &lt;textarea id=&quot;rem&quot; rows=&quot;2&quot;&gt;&lt;/textarea&gt;
            &lt;/div&gt;
            
            &lt;div class=&quot;md:col-span-2 flex flex-wrap gap-3 mt-4&quot;&gt;
                &lt;button type=&quot;submit&quot; id=&quot;submitBtn&quot;&gt;Save&lt;/button&gt;
                &lt;button type=&quot;button&quot; onclick=&quot;scrollToTable()&quot; class=&quot;bg-gray-600&quot;&gt;View Saved List ↓&lt;/button&gt;
                &lt;button type=&quot;button&quot; onclick=&quot;exportJSON()&quot; class=&quot;bg-green-600&quot;&gt;Export JSON&lt;/button&gt;
                &lt;label class=&quot;bg-orange-500 text-white px-6 py-3 rounded-lg cursor-pointer&quot;&gt;
                    Import JSON &lt;input type=&quot;file&quot; id=&quot;importFile&quot; class=&quot;hidden&quot; accept=&quot;.json&quot; onchange=&quot;importJSON(event)&quot;&gt;
                &lt;/label&gt;
            &lt;/div&gt;
        &lt;/form&gt;

        &lt;div id=&quot;tableSection&quot; class=&quot;mt-10&quot;&gt;
            &lt;h3 class=&quot;text-lg font-bold mb-3 italic&quot;&gt;Recent Entries (Local View)&lt;/h3&gt;
            
            &lt;div class=&quot;table-container&quot;&gt;
                &lt;table&gt;
                    &lt;thead class=&quot;bg-gray-200&quot;&gt;
                        &lt;tr&gt;
                            &lt;th&gt;Sr.&lt;/th&gt;
                            &lt;th&gt;Subject&lt;/th&gt;
                            &lt;th&gt;Letter Date&lt;/th&gt;
                            &lt;th&gt;Letter No.&lt;/th&gt;
                            &lt;th&gt;Reply Date&lt;/th&gt;
                            &lt;th class=&quot;text-blue-600&quot;&gt;Status&lt;/th&gt;
                            &lt;th&gt;Action&lt;/th&gt;
                            &lt;th&gt;Remark&lt;/th&gt;
                          &lt;th&gt;Letter Inward No.&lt;/th&gt;
                        &lt;/tr&gt;
                    &lt;/thead&gt;
                    &lt;tbody id=&quot;dataTable&quot;&gt;&lt;/tbody&gt;
                &lt;/table&gt;
            &lt;/div&gt;
            &lt;p class=&quot;text-xs text-gray-400 mt-2&quot;&gt;← Scroll horizontally to see more columns →&lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;
  
  &lt;div class=&quot;container&quot;&gt;

&lt;h1&gt;Letter Correspondence Entry System – Technical Explanation&lt;/h1&gt;

&lt;p&gt;
This web-based application is designed to manage and track official correspondence efficiently.
It enables users to record, update, store, and retrieve letter communication details with a simple interface.
The system combines &lt;strong&gt;form-based data entry&lt;/strong&gt;, &lt;strong&gt;local storage&lt;/strong&gt;, and &lt;strong&gt;cloud integration&lt;/strong&gt;.
&lt;/p&gt;

&lt;h2&gt;1. Objective of the System&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Maintain structured records of incoming and outgoing letters&lt;/li&gt;
&lt;li&gt;Track action taken on each correspondence&lt;/li&gt;
&lt;li&gt;Enable quick editing and deletion of records&lt;/li&gt;
&lt;li&gt;Provide backup via JSON export/import&lt;/li&gt;
&lt;li&gt;Integrate with Google Sheets for centralized data storage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;2. Form Input Structure&lt;/h2&gt;

&lt;p&gt;The form captures key details of correspondence:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sr. No:&lt;/strong&gt; Unique identifier for each entry&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subject:&lt;/strong&gt; Brief description of the letter&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Letter Date:&lt;/strong&gt; Date on the original letter&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Letter Number:&lt;/strong&gt; Reference number of the letter&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Letter Received Date:&lt;/strong&gt; Date when letter is received&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Letter Received Number:&lt;/strong&gt; Inward/receipt number&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action Taken:&lt;/strong&gt; Status of processing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reply Date:&lt;/strong&gt; Date of response&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remarks:&lt;/strong&gt; Additional notes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;3. Action Tracking Logic&lt;/h2&gt;

&lt;p&gt;
The system categorizes each letter based on its processing status:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forwarded&lt;/li&gt;
&lt;li&gt;Reverted&lt;/li&gt;
&lt;li&gt;Filed&lt;/li&gt;
&lt;li class=&quot;highlight&quot;&gt;Action Yet to be Taken (Pending cases)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This helps in monitoring workflow and identifying pending tasks.
&lt;/p&gt;

&lt;h2&gt;4. Data Storage Mechanism&lt;/h2&gt;

&lt;h3&gt;4.1 Local Storage&lt;/h3&gt;

&lt;p&gt;
All entries are stored in the browser using &lt;strong&gt;localStorage&lt;/strong&gt;:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
localStorage.setItem(&#39;letterEntries&#39;, JSON.stringify(letterData));
&lt;/div&gt;

&lt;p&gt;
Benefits:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fast access&lt;/li&gt;
&lt;li&gt;No server dependency&lt;/li&gt;
&lt;li&gt;Offline usability&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;4.2 Cloud Storage (Google Apps Script)&lt;/h3&gt;

&lt;p&gt;
Data is also sent to a Google Sheet using a web API:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
fetch(SCRIPT_URL, {
    method: &#39;POST&#39;,
    mode: &#39;no-cors&#39;,
    body: JSON.stringify(payload)
});
&lt;/div&gt;

&lt;p&gt;
Advantages:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Centralized record keeping&lt;/li&gt;
&lt;li&gt;Multi-user accessibility&lt;/li&gt;
&lt;li&gt;Permanent backup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;5. Data Rendering (Table View)&lt;/h2&gt;

&lt;p&gt;
The system dynamically displays saved entries in a table using JavaScript:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
tbody.innerHTML = letterData.map(...).join(&#39;&#39;);
&lt;/div&gt;

&lt;p&gt;
Features:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Live updates&lt;/li&gt;
&lt;li&gt;Editable rows&lt;/li&gt;
&lt;li&gt;Delete functionality&lt;/li&gt;
&lt;li&gt;Horizontal scroll for wide datasets&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;6. Edit and Update Functionality&lt;/h2&gt;

&lt;p&gt;
When editing a record:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Form fields are pre-filled with existing data&lt;/li&gt;
&lt;li&gt;Submit button changes to &lt;strong&gt;&quot;Update Entry&quot;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Selected record is updated instead of creating a new one&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;code&quot;&gt;
letterData[editIndex] = payload;
&lt;/div&gt;

&lt;h2&gt;7. Delete Functionality&lt;/h2&gt;

&lt;p&gt;
Users can remove records with confirmation:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
letterData.splice(index, 1);
&lt;/div&gt;

&lt;p&gt;
This ensures data integrity and prevents accidental deletion.
&lt;/p&gt;

&lt;h2&gt;8. Backup and Restore System&lt;/h2&gt;

&lt;h3&gt;8.1 Export JSON&lt;/h3&gt;

&lt;p&gt;
Data can be exported as a backup file:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
new Blob([JSON.stringify(letterData, null, 2)], { type: &#39;application/json&#39; });
&lt;/div&gt;

&lt;h3&gt;8.2 Import JSON&lt;/h3&gt;

&lt;p&gt;
Previously saved data can be restored:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File is read using FileReader&lt;/li&gt;
&lt;li&gt;Data replaces current dataset&lt;/li&gt;
&lt;li&gt;Table updates automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;9. User Experience Enhancements&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Smooth scrolling to data table&lt;/li&gt;
&lt;li&gt;Processing indicator during submission&lt;/li&gt;
&lt;li&gt;Dynamic button state (Save → Update)&lt;/li&gt;
&lt;li&gt;Responsive layout using utility classes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;10. Workflow Summary&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;User enters correspondence details&lt;/li&gt;
&lt;li&gt;Clicks &quot;Save&quot;&lt;/li&gt;
&lt;li&gt;Data is stored locally and sent to cloud&lt;/li&gt;
&lt;li&gt;Table updates instantly&lt;/li&gt;
&lt;li&gt;User can edit/delete/export as needed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;11. Engineering &amp; Administrative Benefits&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Efficient document tracking&lt;/li&gt;
&lt;li&gt;Reduced manual register work&lt;/li&gt;
&lt;li&gt;Easy audit and reporting&lt;/li&gt;
&lt;li&gt;Improved accountability&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;12. Limitations&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No authentication system&lt;/li&gt;
&lt;li&gt;Dependent on browser storage&lt;/li&gt;
&lt;li&gt;No validation for duplicate entries&lt;/li&gt;
&lt;li&gt;Limited error handling for API&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;

    &lt;script&gt;
        const SCRIPT_URL = &#39;https://script.google.com/macros/s/AKfycbzYOWmhkHmYuA2WuPGdGRcebSVMWEENwCB8z2k2379HNyto2UIhnw_jrSm9lr4u08nuXQ/exec&#39;;
        let letterData = JSON.parse(localStorage.getItem(&#39;letterEntries&#39;)) || [];
        let editIndex = -1;

        function scrollToTable() {
            document.getElementById(&#39;tableSection&#39;).scrollIntoView({ behavior: &#39;smooth&#39; });
        }

        const renderTable = () =&gt; {
            const tbody = document.getElementById(&#39;dataTable&#39;);
            tbody.innerHTML = letterData.map((item, index) =&gt; `
                &lt;tr class=&quot;hover:bg-gray-50&quot;&gt;
                    &lt;td class=&quot;p-3 border&quot;&gt;${item.sr}&lt;/td&gt;
                    &lt;td class=&quot;p-3 border font-medium&quot;&gt;${item.subj}&lt;/td&gt;
                    &lt;td class=&quot;p-3 border&quot;&gt;${item.l_date}&lt;/td&gt;
                    &lt;td class=&quot;p-3 border&quot;&gt;${item.l_num || &#39;-&#39;}&lt;/td&gt;
                    &lt;td class=&quot;p-3 border&quot;&gt;${item.rep_date || &#39;-&#39;}&lt;/td&gt;
                    &lt;td class=&quot;p-3 border font-bold text-blue-700&quot;&gt;${item.action}&lt;/td&gt;
                    &lt;td class=&quot;p-3 border&quot;&gt;
                        &lt;div class=&quot;flex gap-2&quot;&gt;
                            &lt;button onclick=&quot;editRow(${index})&quot; class=&quot;text-blue-600 underline&quot;&gt;Edit&lt;/button&gt;
                            &lt;button onclick=&quot;deleteRow(${index})&quot; class=&quot;text-red-500 underline&quot;&gt;Delete&lt;/button&gt;
                        &lt;/div&gt;
                    &lt;/td&gt;
                    &lt;td class=&quot;p-3 border&quot;&gt;${item.rem || &#39;-&#39;}&lt;/td&gt;
                    &lt;td class=&quot;p-3 border&quot;&gt;${item.r_num || &#39;-&#39;}&lt;/td&gt;
                &lt;/tr&gt;
            `).join(&#39;&#39;);
            localStorage.setItem(&#39;letterEntries&#39;, JSON.stringify(letterData));
        };

        function editRow(index) {
    const item = letterData[index];
    editIndex = index;
    
    document.getElementById(&#39;sr&#39;).value = item.sr;
    document.getElementById(&#39;subj&#39;).value = item.subj;
    document.getElementById(&#39;l_date&#39;).value = item.l_date;
    document.getElementById(&#39;l_num&#39;).value = item.l_num;
    document.getElementById(&#39;r_date&#39;).value = item.r_date;
    document.getElementById(&#39;r_num&#39;).value = item.r_num || &#39;&#39;; // ADD THIS
    document.getElementById(&#39;action&#39;).value = item.action;
    document.getElementById(&#39;rep_date&#39;).value = item.rep_date;
    document.getElementById(&#39;rem&#39;).value = item.rem;

    const btn = document.getElementById(&#39;submitBtn&#39;);
    btn.innerText = &quot;Update Entry&quot;;
    btn.classList.add(&#39;bg-yellow-600&#39;);
    window.scrollTo({ top: 0, behavior: &#39;smooth&#39; });
}

        document.getElementById(&#39;letterForm&#39;).addEventListener(&#39;submit&#39;, async (e) =&gt; {
            e.preventDefault();
            const submitBtn = document.getElementById(&#39;submitBtn&#39;);
            submitBtn.disabled = true;
            submitBtn.innerText = &quot;Processing...&quot;;

            const payload = {
    sr: document.getElementById(&#39;sr&#39;).value,
    subj: document.getElementById(&#39;subj&#39;).value,
    l_date: document.getElementById(&#39;l_date&#39;).value,
    l_num: document.getElementById(&#39;l_num&#39;).value,
    r_date: document.getElementById(&#39;r_date&#39;).value,
    r_num: document.getElementById(&#39;r_num&#39;).value, // ADD THIS
    action: document.getElementById(&#39;action&#39;).value,
    rep_date: document.getElementById(&#39;rep_date&#39;).value,
    rem: document.getElementById(&#39;rem&#39;).value
};

            try {
                await fetch(SCRIPT_URL, { method: &#39;POST&#39;, mode: &#39;no-cors&#39;, body: JSON.stringify(payload) });

                if (editIndex === -1) {
                    letterData.push(payload);
                } else {
                    letterData[editIndex] = payload;
                    editIndex = -1;
                }

                renderTable();
                e.target.reset();
                submitBtn.innerText = &quot;Save&quot;;
                submitBtn.classList.remove(&#39;bg-yellow-600&#39;);
                
                setTimeout(scrollToTable, 500); 

            } catch (error) {
                alert(&#39;Error connecting to Sheet.&#39;);
            } finally {
                submitBtn.disabled = false;
            }
        });

        function deleteRow(index) {
            if(confirm(&quot;Delete record?&quot;)) {
                letterData.splice(index, 1);
                renderTable();
            }
        }

        function exportJSON() {
            const blob = new Blob([JSON.stringify(letterData, null, 2)], { type: &#39;application/json&#39; });
            const a = document.createElement(&#39;a&#39;);
            a.href = URL.createObjectURL(blob);
            a.download = &#39;backup.json&#39;;
            a.click();
        }

        function importJSON(event) {
            const reader = new FileReader();
            reader.onload = (e) =&gt; {
                letterData = JSON.parse(e.target.result);
                renderTable();
                scrollToTable();
            };
            reader.readAsText(event.target.files[0]);
        }

        renderTable();
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/03/letter-correspondence.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-8700580112072653133</guid><pubDate>Thu, 19 Mar 2026 02:32:58 +0000</pubDate><atom:updated>2026-06-23T14:08:28.314+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Design calculations</category><category domain="http://www.blogger.com/atom/ns#">Software</category><title>PUMP DESIGN CALCULATION</title><description>
&lt;style&gt;
body {
    font-family: &#39;Segoe UI&#39;, Arial, sans-serif;
    background: #f4f6f9;
    color: #333;
    line-height: 1.6;
    padding: 20px;
}
.container {
    max-width: 1100px;
    margin: auto;
    background: #fff;
    padding: 30px;
    border-radius: 10px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.1);
}
h1, h2 {
    color: #1a5276;
}
h2 {
    border-left: 5px solid #3498db;
    padding-left: 10px;
}
ul {
    margin-left: 20px;
}
.code {
    background: #f8f9fa;
    padding: 10px;
    border-left: 4px solid #3498db;
    font-family: monospace;
}
.highlight {
    color: #e74c3c;
    font-weight: bold;
}
&lt;/style&gt;


&lt;div id=&quot;pump-calculator-container&quot; style=&quot;font-family: &#39;Segoe UI&#39;, Arial, sans-serif; max-width: 600px; margin: 20px auto; padding: 25px; border: 1px solid #ccc; border-radius: 12px; background-color: #ffffff; box-shadow: 0 10px 20px rgba(0,0,0,0.1);&quot;&gt;
    
    &lt;div id=&quot;print-header&quot; style=&quot;display: none; text-align: center; border-bottom: 2px solid #000; margin-bottom: 20px;&quot;&gt;
        &lt;h1&gt;PUMP DESIGN CALCULATION REPORT&lt;/h1&gt;
        &lt;p&gt;Project Infrastructure Analysis | Date: &lt;span id=&quot;print-date&quot;&gt;&lt;/span&gt;&lt;/p&gt;
    &lt;/div&gt;

    &lt;h2 id=&quot;calc-title&quot; style=&quot;text-align: center; color: #1a5276; border-bottom: 2px solid #3498db; padding-bottom: 10px;&quot;&gt;Pump Design &amp; Data Logger&lt;/h2&gt;
    
    &lt;div style=&quot;display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px;&quot;&gt;
        &lt;div&gt;&lt;label&gt;Suction (z1) m:&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;z1&quot; value=&quot;0&quot; style=&quot;width:90%; padding:5px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Discharge (z2) m:&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;z2&quot; value=&quot;20&quot; style=&quot;width:90%; padding:5px;&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div style=&quot;margin-bottom: 15px;&quot;&gt;
        &lt;label&gt;Pipe Length (L) m:&lt;/label&gt;
        &lt;input type=&quot;number&quot; id=&quot;pipeLength&quot; value=&quot;500&quot; style=&quot;width:95%; padding:5px;&quot;&gt;
    &lt;/div&gt;
    &lt;div style=&quot;display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px;&quot;&gt;
        &lt;div&gt;&lt;label&gt;Dia (D) mm:&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;diameter&quot; value=&quot;150&quot; style=&quot;width:90%; padding:5px;&quot;&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label&gt;Flow (Q) m³/hr:&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;flowRate&quot; value=&quot;50&quot; style=&quot;width:90%; padding:5px;&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;div id=&quot;action-buttons&quot;&gt;
        &lt;button onclick=&quot;calculateAndShow()&quot; style=&quot;width: 100%; padding: 12px; background-color: #27ae60; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; margin-bottom: 10px;&quot;&gt;1. Calculate System&lt;/button&gt;
    &lt;/div&gt;

    &lt;div id=&quot;fullResult&quot; style=&quot;margin-top: 15px; padding: 15px; background-color: #f4fbf7; border: 1px solid #d5f5e3; border-radius: 8px; display: none;&quot;&gt;
        &lt;h4 style=&quot;margin-top:0;&quot;&gt;Calculation Results:&lt;/h4&gt;
        &lt;p&gt;Static Head: &lt;span id=&quot;resStatic&quot;&gt;0&lt;/span&gt; m&lt;/p&gt;
        &lt;p&gt;Friction Loss: &lt;span id=&quot;resFric&quot;&gt;0&lt;/span&gt; m&lt;/p&gt;
        &lt;p&gt;&lt;strong&gt;Total Dynamic Head (TDH):&lt;/strong&gt; &lt;span id=&quot;resTdh&quot;&gt;0&lt;/span&gt; m&lt;/p&gt;
        &lt;p&gt;&lt;strong&gt;Required Power:&lt;/strong&gt; &lt;span id=&quot;resKw&quot;&gt;0&lt;/span&gt; kW (&lt;span id=&quot;resHp&quot;&gt;0&lt;/span&gt; HP)&lt;/p&gt;
        
        &lt;div id=&quot;export-actions&quot; style=&quot;display: flex; gap: 10px; margin-top: 15px;&quot;&gt;
            &lt;button onclick=&quot;sendToSheet()&quot; style=&quot;flex: 1; padding: 10px; background-color: #f39c12; color: white; border: none; border-radius: 4px; cursor: pointer;&quot;&gt;Save to Sheet&lt;/button&gt;
            &lt;button onclick=&quot;prepareAndPrint()&quot; style=&quot;flex: 1; padding: 10px; background-color: #34495e; color: white; border: none; border-radius: 4px; cursor: pointer;&quot;&gt;Save as PDF&lt;/button&gt;
        &lt;/div&gt;
        &lt;p id=&quot;statusMsg&quot; style=&quot;font-size: 11px; text-align: center; color: #7f8c8d; margin-top: 5px;&quot;&gt;&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&quot;container&quot;&gt;

&lt;h1&gt;Pump Design &amp; Data Logger – Technical Explanation&lt;/h1&gt;

&lt;p&gt;
This tool is developed for &lt;strong&gt;hydraulic pump system design&lt;/strong&gt; and performance estimation.
It calculates the &lt;strong&gt;Total Dynamic Head (TDH)&lt;/strong&gt; and required pump power based on
pipe flow conditions and elevation differences.
&lt;/p&gt;

&lt;h2&gt;1. Objective of the Tool&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Estimate pump head requirements&lt;/li&gt;
&lt;li&gt;Calculate friction losses in pipelines&lt;/li&gt;
&lt;li&gt;Determine pump power (kW and HP)&lt;/li&gt;
&lt;li&gt;Generate printable design reports&lt;/li&gt;
&lt;li&gt;Store and export calculation data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;2. Input Parameters&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Suction Level (z₁):&lt;/strong&gt; Pump inlet elevation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discharge Level (z₂):&lt;/strong&gt; Outlet elevation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pipe Length (L):&lt;/strong&gt; Total pipeline length&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pipe Diameter (D):&lt;/strong&gt; Internal diameter of pipe&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flow Rate (Q):&lt;/strong&gt; Discharge in m³/hr&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;3. Hydraulic Calculations&lt;/h2&gt;

&lt;h3&gt;3.1 Static Head&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Static Head = z₂ - z₁
&lt;/div&gt;

&lt;p&gt;
Represents elevation difference between suction and discharge points.
&lt;/p&gt;

&lt;h3&gt;3.2 Flow Conversion&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Q (m³/s) = Q (m³/hr) / 3600
&lt;/div&gt;

&lt;p&gt;
Required for SI unit consistency.
&lt;/p&gt;

&lt;h3&gt;3.3 Pipe Diameter Conversion&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
D (m) = D (mm) / 1000
&lt;/div&gt;

&lt;h3&gt;3.4 Friction Loss (Hazen-Williams Equation)&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
hf = (10.67 × L × Q^1.852) / (C^1.852 × D^4.87)
&lt;/div&gt;

&lt;p&gt;
Where:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;hf = friction head loss (m)&lt;/li&gt;
&lt;li&gt;C = Hazen-Williams coefficient (assumed 130)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This formula is widely used for water supply systems and provides reliable estimates for turbulent flow.
&lt;/p&gt;

&lt;h3&gt;3.5 Total Dynamic Head (TDH)&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
TDH = Static Head + Friction Loss
&lt;/div&gt;

&lt;p&gt;
This represents the total head against which the pump must operate.
&lt;/p&gt;

&lt;h3&gt;3.6 Pump Power Calculation&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Power (kW) = (ρ × g × Q × TDH) / (η × 1000)
&lt;/div&gt;

&lt;p&gt;
Where:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ρ = density of water (1000 kg/m³)&lt;/li&gt;
&lt;li&gt;g = 9.81 m/s²&lt;/li&gt;
&lt;li&gt;η = pump efficiency (assumed 75%)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;3.7 Conversion to Horsepower&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
HP = kW × 1.341
&lt;/div&gt;

&lt;h2&gt;4. System Workflow&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;User enters hydraulic parameters&lt;/li&gt;
&lt;li&gt;Clicks &lt;strong&gt;&quot;Calculate System&quot;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;System computes all hydraulic values&lt;/li&gt;
&lt;li&gt;Results are displayed instantly&lt;/li&gt;
&lt;li&gt;User can export or print results&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;5. Data Logging Feature&lt;/h2&gt;

&lt;p&gt;
The system stores the last calculation in memory:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
lastCalculation = { flow, head, friction, tdh, kw, hp }
&lt;/div&gt;

&lt;p&gt;
This enables:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quick export to external systems&lt;/li&gt;
&lt;li&gt;Cloud storage integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;6. Google Sheets Integration&lt;/h2&gt;

&lt;p&gt;
The tool supports saving results to Google Sheets via API:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
fetch(scriptUrl, {
    method: &#39;POST&#39;,
    mode: &#39;no-cors&#39;,
    body: JSON.stringify(lastCalculation)
});
&lt;/div&gt;

&lt;p&gt;
Benefits:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Centralized data storage&lt;/li&gt;
&lt;li&gt;Project record keeping&lt;/li&gt;
&lt;li&gt;Multi-user accessibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;7. Print &amp; PDF Report Generation&lt;/h2&gt;

&lt;p&gt;
The tool includes a print-optimized layout:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hides buttons and UI elements&lt;/li&gt;
&lt;li&gt;Displays formatted report header&lt;/li&gt;
&lt;li&gt;Auto inserts current date&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;code&quot;&gt;
window.print();
&lt;/div&gt;

&lt;p&gt;
This allows generation of professional design reports.
&lt;/p&gt;

&lt;h2&gt;8. Engineering Significance&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ensures correct pump selection&lt;/li&gt;
&lt;li&gt;Avoids under/over-design&lt;/li&gt;
&lt;li&gt;Optimizes energy consumption&lt;/li&gt;
&lt;li&gt;Improves system reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;9. Assumptions&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Water as working fluid&lt;/li&gt;
&lt;li&gt;Constant pipe roughness (C = 130)&lt;/li&gt;
&lt;li&gt;Pump efficiency = 75%&lt;/li&gt;
&lt;li&gt;Steady flow conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;10. Limitations&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No minor losses (bends, valves) considered&lt;/li&gt;
&lt;li&gt;No NPSH calculation&lt;/li&gt;
&lt;li&gt;No pump curve matching&lt;/li&gt;
&lt;li&gt;No transient flow analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;11. Conclusion&lt;/h2&gt;

&lt;p&gt;
This tool serves as a &lt;span class=&quot;highlight&quot;&gt;quick and effective hydraulic design assistant&lt;/span&gt;
for engineers. It simplifies complex calculations into a user-friendly interface while maintaining
engineering accuracy for preliminary design.
&lt;/p&gt;

&lt;p&gt;
For final pump selection, it is recommended to validate results with manufacturer pump curves
and detailed hydraulic analysis.
&lt;/p&gt;

&lt;/div&gt;

&lt;style&gt;
@media print {
    body * { visibility: hidden; }
    #pump-calculator-container, #pump-calculator-container * { visibility: visible; }
    #pump-calculator-container { position: absolute; left: 0; top: 0; width: 100%; border: none; box-shadow: none; }
    #action-buttons, #export-actions, #statusMsg { display: none !important; }
    #print-header { display: block !important; }
    input { border: none !important; background: transparent !important; }
}
&lt;/style&gt;

&lt;script&gt;
let lastCalculation = {};

function calculateAndShow() {
    const z1 = parseFloat(document.getElementById(&#39;z1&#39;).value);
    const z2 = parseFloat(document.getElementById(&#39;z2&#39;).value);
    const L = parseFloat(document.getElementById(&#39;pipeLength&#39;).value);
    const D_mm = parseFloat(document.getElementById(&#39;diameter&#39;).value);
    const Q_hr = parseFloat(document.getElementById(&#39;flowRate&#39;).value);
    
    const staticH = z2 - z1;
    const Q_sec = Q_hr / 3600;
    const D_m = D_mm / 1000;
    const hf = (10.67 * L * Math.pow(Q_sec, 1.852)) / (Math.pow(130, 1.852) * Math.pow(D_m, 4.87));
    const tdh = staticH + hf;
    const kw = (1000 * 9.81 * Q_sec * tdh) / (0.75 * 1000);
    const hp = kw * 1.341;

    lastCalculation = { flow: Q_hr, head: staticH, friction: hf.toFixed(2), tdh: tdh.toFixed(2), kw: kw.toFixed(2), hp: hp.toFixed(2) };

    document.getElementById(&#39;resStatic&#39;).innerText = staticH.toFixed(2);
    document.getElementById(&#39;resFric&#39;).innerText = hf.toFixed(2);
    document.getElementById(&#39;resTdh&#39;).innerText = tdh.toFixed(2);
    document.getElementById(&#39;resKw&#39;).innerText = kw.toFixed(2);
    document.getElementById(&#39;resHp&#39;).innerText = hp.toFixed(2);
    document.getElementById(&#39;fullResult&#39;).style.display = &#39;block&#39;;
}

function prepareAndPrint() {
    document.getElementById(&#39;print-date&#39;).innerText = new Date().toLocaleDateString();
    window.print();
}

function sendToSheet() {
    const scriptUrl = &#39;YOUR_SCRIPT_URL_HERE&#39;; 
    if(scriptUrl === &#39;YOUR_SCRIPT_URL_HERE&#39;) { alert(&quot;Please add your Google Script URL first!&quot;); return; }
    
    document.getElementById(&#39;statusMsg&#39;).innerText = &quot;Sending to Sheets...&quot;;
    fetch(scriptUrl, { method: &#39;POST&#39;, mode: &#39;no-cors&#39;, body: JSON.stringify(lastCalculation) })
    .then(() =&gt; { document.getElementById(&#39;statusMsg&#39;).innerText = &quot;Data Saved Successfully!&quot;; })
    .catch(() =&gt; { document.getElementById(&#39;statusMsg&#39;).innerText = &quot;Error saving data.&quot;; });
}
&lt;/script&gt;
&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/03/pump-design-calculation.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-41499563337414015</guid><pubDate>Wed, 18 Mar 2026 18:56:55 +0000</pubDate><atom:updated>2026-06-23T14:08:50.652+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">Design calculations</category><category domain="http://www.blogger.com/atom/ns#">Software</category><title>Isolated footing design as per IS 456 2000</title><description>&lt;div id=&quot;footing-pro-container&quot;&gt;
    &lt;style&gt;
        #footing-pro-container {
            background: #ffffff;
            border: 1px solid #333;
            border-radius: 8px;
            padding: 20px;
            max-width: 600px;
            margin: 20px auto;
            font-family: &#39;Segoe UI&#39;, Tahoma, sans-serif;
            color: #222;
            box-shadow: 0 10px 30px rgba(0,0,0,0.1);
        }
        .header { text-align: center; border-bottom: 2px solid #2c3e50; margin-bottom: 20px; padding-bottom: 10px; }
        .input-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px; }
        .input-group label { display: block; font-size: 12px; font-weight: bold; margin-bottom: 5px; color: #555; }
        .input-group input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }
        
        #calc-btn {
            width: 100%;
            background: #2c3e50;
            color: white;
            padding: 15px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-weight: bold;
            font-size: 16px;
        }
        #calc-btn:hover { background: #1a252f; }

        .report-section {
            margin-top: 25px;
            display: none;
            border-top: 2px dashed #ccc;
            padding-top: 20px;
        }
        .step { margin-bottom: 20px; padding: 10px; background: #fdfdfd; border-left: 4px solid #3498db; }
        .step-title { font-weight: bold; color: #2980b9; text-transform: uppercase; font-size: 13px; margin-bottom: 8px; }
        .formula { font-family: &#39;Courier New&#39;, monospace; background: #eee; padding: 5px; display: inline-block; margin: 5px 0; font-weight: bold; }
        .final-val { color: #c0392b; font-weight: bold; }
      
body {
    font-family: &#39;Segoe UI&#39;, Arial, sans-serif;
    background: #f4f6f9;
    color: #333;
    line-height: 1.6;
    padding: 20px;
}
.container {
    max-width: 1100px;
    margin: auto;
    background: #fff;
    padding: 30px;
    border-radius: 10px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.1);
}
h1, h2 {
    color: #1a3a5a;
}
h2 {
    border-left: 5px solid #3498db;
    padding-left: 10px;
}
ul {
    margin-left: 20px;
}
.code {
    background: #f8f9fa;
    padding: 10px;
    border-left: 4px solid #3498db;
    font-family: monospace;
}
.highlight {
    color: #e74c3c;
    font-weight: bold;
}
    &lt;/style&gt;

    &lt;div class=&quot;header&quot;&gt;
        &lt;h2 style=&quot;margin:0;&quot;&gt;RCC Isolated Footing Design&lt;/h2&gt;
        &lt;small&gt;As per IS 456:2000 Standards&lt;/small&gt;
    &lt;/div&gt;

    &lt;div class=&quot;input-grid&quot;&gt;
        &lt;div class=&quot;input-group&quot;&gt;
            &lt;label&gt;Column Load (P) in kN&lt;/label&gt;
            &lt;input type=&quot;number&quot; id=&quot;P&quot; value=&quot;1000&quot;&gt;
        &lt;/div&gt;
        &lt;div class=&quot;input-group&quot;&gt;
            &lt;label&gt;SBC of Soil in kN/m²&lt;/label&gt;
            &lt;input type=&quot;number&quot; id=&quot;SBC&quot; value=&quot;200&quot;&gt;
        &lt;/div&gt;
        &lt;div class=&quot;input-group&quot;&gt;
            &lt;label&gt;Column Size (mm)&lt;/label&gt;
            &lt;input type=&quot;number&quot; id=&quot;col_size&quot; value=&quot;400&quot;&gt;
        &lt;/div&gt;
        &lt;div class=&quot;input-group&quot;&gt;
            &lt;label&gt;Steel Grade (fy)&lt;/label&gt;
            &lt;input type=&quot;number&quot; id=&quot;fy&quot; value=&quot;500&quot;&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;button id=&quot;calc-btn&quot; onclick=&quot;generateReport()&quot;&gt;Generate Detailed Report&lt;/button&gt;

    &lt;div id=&quot;report&quot; class=&quot;report-section&quot;&gt;
        &lt;div class=&quot;step&quot;&gt;
            &lt;div class=&quot;step-title&quot;&gt;Step 1: Required Footing Area&lt;/div&gt;
            Increasing load by 10% for self-weight...&lt;br&gt;
            &lt;div class=&quot;formula&quot;&gt;A = (P * 1.1) / SBC&lt;/div&gt;&lt;br&gt;
            Required Area: &lt;span id=&quot;r1&quot; class=&quot;final-val&quot;&gt;&lt;/span&gt; m²&lt;br&gt;
            Adopted Size: &lt;span id=&quot;r2&quot; class=&quot;final-val&quot;&gt;&lt;/span&gt; m x &lt;span id=&quot;r2_2&quot; class=&quot;final-val&quot;&gt;&lt;/span&gt; m
        &lt;/div&gt;

        &lt;div class=&quot;step&quot;&gt;
            &lt;div class=&quot;step-title&quot;&gt;Step 2: Net Upward Pressure (q)&lt;/div&gt;
            &lt;div class=&quot;formula&quot;&gt;q = P / Area_Provided&lt;/div&gt;&lt;br&gt;
            Net Pressure: &lt;span id=&quot;r3&quot; class=&quot;final-val&quot;&gt;&lt;/span&gt; kN/m²
        &lt;/div&gt;

        &lt;div class=&quot;step&quot;&gt;
            &lt;div class=&quot;step-title&quot;&gt;Step 3: Bending Moment (M)&lt;/div&gt;
            Critical section at face of column...&lt;br&gt;
            Projection (X) = (Side - Col)/2 = &lt;span id=&quot;r_x&quot;&gt;&lt;/span&gt; m&lt;br&gt;
            &lt;div class=&quot;formula&quot;&gt;M = (q * X²) / 2&lt;/div&gt;&lt;br&gt;
            Moment: &lt;span id=&quot;r4&quot; class=&quot;final-val&quot;&gt;&lt;/span&gt; kNm
        &lt;/div&gt;

        &lt;div class=&quot;step&quot;&gt;
            &lt;div class=&quot;step-title&quot;&gt;Step 4: Steel Calculation (Ast)&lt;/div&gt;
            Using Effective Depth (d) = 400mm&lt;br&gt;
            &lt;div class=&quot;formula&quot;&gt;Ast = (M * 1.5) / (0.87 * fy * j * d)&lt;/div&gt;&lt;br&gt;
            Required Ast: &lt;span id=&quot;r5&quot; class=&quot;final-val&quot;&gt;&lt;/span&gt; mm²&lt;br&gt;
            &lt;strong&gt;Result:&lt;/strong&gt; Provide 12mm bars @ &lt;span id=&quot;r6&quot;&gt;&lt;/span&gt; mm c/c.
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;container&quot;&gt;

&lt;h1&gt;RCC Isolated Footing Design Tool – Technical Explanation&lt;/h1&gt;

&lt;p&gt;
This tool is developed for the &lt;strong&gt;design of isolated footings&lt;/strong&gt; supporting individual columns,
based on guidelines from &lt;strong&gt;IS 456:2000&lt;/strong&gt;. It provides a step-by-step calculation of
footing size, soil pressure, bending moment, and reinforcement requirement.
&lt;/p&gt;

&lt;h2&gt;1. Objective of the Tool&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Determine required footing area&lt;/li&gt;
&lt;li&gt;Check soil bearing pressure&lt;/li&gt;
&lt;li&gt;Calculate bending moment at critical section&lt;/li&gt;
&lt;li&gt;Design reinforcement (Ast)&lt;/li&gt;
&lt;li&gt;Provide practical bar spacing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;2. Input Parameters&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Column Load (P):&lt;/strong&gt; Axial load on footing (kN)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Safe Bearing Capacity (SBC):&lt;/strong&gt; Soil capacity (kN/m²)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Column Size:&lt;/strong&gt; Size of column (mm)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Steel Grade (fy):&lt;/strong&gt; Yield strength of reinforcement (MPa)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;3. Design Procedure&lt;/h2&gt;

&lt;h3&gt;Step 1: Footing Area Calculation&lt;/h3&gt;

&lt;p&gt;
To account for self-weight of footing, load is increased by 10%.
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
A = (P × 1.1) / SBC
&lt;/div&gt;

&lt;p&gt;
The footing is assumed square:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Side = √A
&lt;/div&gt;

&lt;p&gt;
The value is rounded for practical construction.
&lt;/p&gt;

&lt;h3&gt;Step 2: Net Soil Pressure&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
q = P / Area_provided
&lt;/div&gt;

&lt;p&gt;
This ensures:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Actual pressure is within SBC limits&lt;/li&gt;
&lt;li&gt;Uniform load distribution assumption&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Step 3: Bending Moment Calculation&lt;/h3&gt;

&lt;p&gt;
Critical section is taken at the face of the column.
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Projection (X) = (Footing Size - Column Size) / 2
&lt;/div&gt;

&lt;div class=&quot;code&quot;&gt;
M = (q × X²) / 2
&lt;/div&gt;

&lt;p&gt;
Factored moment:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Mu = 1.5 × M
&lt;/div&gt;

&lt;p&gt;
This follows limit state design principles.
&lt;/p&gt;

&lt;h3&gt;Step 4: Steel Reinforcement (Ast)&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Ast = (Mu × 10⁶) / (0.87 × fy × j × d)
&lt;/div&gt;

&lt;p&gt;
Where:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;j ≈ 0.9 (lever arm factor)&lt;/li&gt;
&lt;li&gt;d = effective depth (assumed 400 mm)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Step 5: Bar Spacing&lt;/h3&gt;

&lt;p&gt;
Using 12 mm diameter bars:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Area of bar = 113 mm²
&lt;/div&gt;

&lt;div class=&quot;code&quot;&gt;
Spacing = (Area × 1000) / (Ast / Footing Width)
&lt;/div&gt;

&lt;p&gt;
Maximum spacing is limited:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Spacing ≤ 300 mm
&lt;/div&gt;

&lt;h2&gt;4. Engineering Significance&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ensures safe load transfer to soil&lt;/li&gt;
&lt;li&gt;Prevents excessive settlement&lt;/li&gt;
&lt;li&gt;Controls bending failure&lt;/li&gt;
&lt;li&gt;Provides economical reinforcement design&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;5. Assumptions&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Uniform soil pressure distribution&lt;/li&gt;
&lt;li&gt;Square footing geometry&lt;/li&gt;
&lt;li&gt;Effective depth fixed at 400 mm&lt;/li&gt;
&lt;li&gt;No eccentric loading considered&lt;/li&gt;
&lt;li&gt;Only bending design (no shear checks included)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;6. Limitations&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No check for one-way shear&lt;/li&gt;
&lt;li&gt;No check for punching shear&lt;/li&gt;
&lt;li&gt;No settlement analysis&lt;/li&gt;
&lt;li&gt;No seismic or moment effects&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;7. Workflow Summary&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;User inputs load, SBC, column size, and steel grade&lt;/li&gt;
&lt;li&gt;Tool calculates required area&lt;/li&gt;
&lt;li&gt;Adopted footing size is determined&lt;/li&gt;
&lt;li&gt;Soil pressure and bending moment are computed&lt;/li&gt;
&lt;li&gt;Steel reinforcement is designed&lt;/li&gt;
&lt;li&gt;Bar spacing is suggested&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;8. Conclusion&lt;/h2&gt;

&lt;p&gt;
This tool acts as a &lt;span class=&quot;highlight&quot;&gt;rapid preliminary design assistant&lt;/span&gt; for RCC isolated footings.
It simplifies complex structural calculations into a clear step-by-step process, making it highly useful
for site engineers and designers.
&lt;/p&gt;

&lt;p&gt;
For final design, it is essential to perform detailed checks including shear, settlement,
and code compliance as per IS 456:2000.
&lt;/p&gt;

&lt;/div&gt;

    &lt;script&gt;
        function generateReport() {
            // Inputs
            const P = parseFloat(document.getElementById(&#39;P&#39;).value);
            const SBC = parseFloat(document.getElementById(&#39;SBC&#39;).value);
            const col = parseFloat(document.getElementById(&#39;col_size&#39;).value) / 1000;
            const fy = parseFloat(document.getElementById(&#39;fy&#39;).value);

            if(!P || !SBC) return;

            // Step 1: Area
            let AreaReq = (P * 1.1) / SBC;
            let Side = Math.ceil(Math.sqrt(AreaReq) * 10) / 10;
            let AreaProvided = Side * Side;

            // Step 2: Pressure
            let q = P / AreaProvided;

            // Step 3: Moment
            let X = (Side - col) / 2;
            let M = (q * Math.pow(X, 2)) / 2;
            let Mu = M * 1.5; // Factored

            // Step 4: Steel
            let d = 400; // Effective depth assumed from your image
            let Ast = (Mu * Math.pow(10, 6)) / (0.87 * fy * 0.9 * d);
            
            // Spacing for 12mm bar (Area = 113mm2)
            let spacing = (113 * 1000) / (Ast / Side); 
            if (spacing &gt; 300) spacing = 300; // Max spacing limit

            // UI Update
            document.getElementById(&#39;report&#39;).style.display = &#39;block&#39;;
            document.getElementById(&#39;r1&#39;).innerText = AreaReq.toFixed(2);
            document.getElementById(&#39;r2&#39;).innerText = Side.toFixed(2);
            document.getElementById(&#39;r2_2&#39;).innerText = Side.toFixed(2);
            document.getElementById(&#39;r3&#39;).innerText = q.toFixed(2);
            document.getElementById(&#39;r_x&#39;).innerText = X.toFixed(2);
            document.getElementById(&#39;r4&#39;).innerText = M.toFixed(2);
            document.getElementById(&#39;r5&#39;).innerText = Math.round(Ast);
            document.getElementById(&#39;r6&#39;).innerText = Math.round(spacing);
        }
    &lt;/script&gt;
&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/03/isolated-footing-design-as-per-is-456.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-4082034759430863561</guid><pubDate>Wed, 18 Mar 2026 18:44:43 +0000</pubDate><atom:updated>2026-04-06T12:27:31.330+05:30</atom:updated><title>Helical Ring length calculator </title><description>&lt;div id=&quot;helical-calc-container&quot;&gt;
    &lt;style&gt;
        #helical-calc-container {
            background: #ffffff;
            border: 1px solid #d1d5db;
            border-radius: 10px;
            padding: 20px;
            max-width: 450px;
            margin: 20px auto;
            font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif;
            color: #374151;
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
        }
        .h-header { text-align: center; border-bottom: 2px solid #3b82f6; padding-bottom: 10px; margin-bottom: 20px; }
        .h-header h2 { margin: 0; font-size: 1.25rem; color: #1e40af; }
        
        .h-row { margin-bottom: 15px; }
        .h-row label { display: block; font-size: 14px; font-weight: 600; margin-bottom: 5px; }
        
        .h-input {
            width: 100%;
            padding: 10px;
            border: 1px solid #d1d5db;
            border-radius: 6px;
            box-sizing: border-box;
            font-size: 15px;
        }
        .h-input:focus { outline: 2px solid #3b82f6; border-color: transparent; }

        #h-btn {
            width: 100%;
            background-color: #1e40af;
            color: white;
            border: none;
            padding: 12px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 16px;
            font-weight: bold;
            margin-top: 10px;
        }
        #h-btn:hover { background-color: #1d4ed8; }

        #h-result-box {
            margin-top: 20px;
            padding: 15px;
            background: #eff6ff;
            border-left: 5px solid #3b82f6;
            display: none;
        }
        .res-line { font-size: 1.1em; margin: 5px 0; }
        .formula-note { font-size: 0.8em; color: #6b7280; font-style: italic; margin-top: 10px; }
    &lt;/style&gt;

    &lt;div class=&quot;h-header&quot;&gt;
        &lt;h2&gt;Helical Ring Length Calculator&lt;/h2&gt;
    &lt;/div&gt;

    &lt;div class=&quot;h-row&quot;&gt;
        &lt;label&gt;Total Height of Spiral (m)&lt;/label&gt;
        &lt;input type=&quot;number&quot; id=&quot;h_height&quot; class=&quot;h-input&quot; placeholder=&quot;e.g. 3.0&quot; step=&quot;0.01&quot;&gt;
    &lt;/div&gt;

    &lt;div class=&quot;h-row&quot;&gt;
        &lt;label&gt;Diameter of Ring (m) &lt;br&gt;&lt;small&gt;(Center-to-center of bar)&lt;/small&gt;&lt;/label&gt;
        &lt;input type=&quot;number&quot; id=&quot;h_dia&quot; class=&quot;h-input&quot; placeholder=&quot;e.g. 0.5&quot; step=&quot;0.01&quot;&gt;
    &lt;/div&gt;

    &lt;div class=&quot;h-row&quot;&gt;
        &lt;label&gt;Pitch / Spacing (m)&lt;/label&gt;
        &lt;input type=&quot;number&quot; id=&quot;h_pitch&quot; class=&quot;h-input&quot; placeholder=&quot;e.g. 0.15&quot; step=&quot;0.01&quot;&gt;
    &lt;/div&gt;

    &lt;button id=&quot;h-btn&quot; onclick=&quot;calcHelical()&quot;&gt;Calculate Length&lt;/button&gt;

    &lt;div id=&quot;h-result-box&quot;&gt;
        &lt;div class=&quot;res-line&quot;&gt;Number of Turns: &lt;strong id=&quot;out_turns&quot;&gt;0&lt;/strong&gt;&lt;/div&gt;
        &lt;div class=&quot;res-line&quot;&gt;Total Bar Length: &lt;strong id=&quot;out_len&quot; style=&quot;color: #1e40af;&quot;&gt;0.00 m&lt;/strong&gt;&lt;/div&gt;
        &lt;p class=&quot;formula-note&quot;&gt;Formula: L = n × √(C² + P²)&lt;br&gt;Includes circumference and pitch incline.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  
  &lt;div class=&quot;container&quot;&gt;

&lt;h1&gt;Helical Ring Length Calculator – Technical Explanation&lt;/h1&gt;

&lt;p&gt;
This tool is designed to calculate the &lt;strong&gt;total length of helical reinforcement&lt;/strong&gt;
(commonly used in columns, piles, and spiral reinforcement systems).
It is based on fundamental geometric relationships of a helix.
&lt;/p&gt;

&lt;h2&gt;1. Objective of the Tool&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Calculate number of helical turns&lt;/li&gt;
&lt;li&gt;Determine total reinforcement length&lt;/li&gt;
&lt;li&gt;Assist in bar bending schedule (BBS)&lt;/li&gt;
&lt;li&gt;Improve accuracy in spiral reinforcement estimation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;2. Input Parameters&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Total Height (H):&lt;/strong&gt; Vertical height of spiral (m)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Diameter (D):&lt;/strong&gt; Diameter of helix (center-to-center of bar)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pitch (P):&lt;/strong&gt; Vertical spacing between turns&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;3. Geometric Concept&lt;/h2&gt;

&lt;p&gt;
A helical bar forms a &lt;strong&gt;3D spiral path&lt;/strong&gt; around a cylinder.
Each turn consists of:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Circular movement (circumference)&lt;/li&gt;
&lt;li&gt;Vertical rise (pitch)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Thus, the length of one turn is the &lt;strong&gt;hypotenuse of a right triangle&lt;/strong&gt;.
&lt;/p&gt;

&lt;h2&gt;4. Calculation Steps&lt;/h2&gt;

&lt;h3&gt;Step 1: Number of Turns&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
n = H / P
&lt;/div&gt;

&lt;p&gt;
This represents how many complete spiral loops are formed.
&lt;/p&gt;

&lt;h3&gt;Step 2: Circumference of One Turn&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
C = π × D
&lt;/div&gt;

&lt;p&gt;
This is the horizontal distance covered in one revolution.
&lt;/p&gt;

&lt;h3&gt;Step 3: Length of One Turn&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
L_turn = √(C² + P²)
&lt;/div&gt;

&lt;p&gt;
This combines horizontal and vertical components using Pythagoras theorem.
&lt;/p&gt;

&lt;h3&gt;Step 4: Total Length of Helical Bar&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Total Length = n × L_turn
&lt;/div&gt;

&lt;p&gt;
This gives the full length of reinforcement required.
&lt;/p&gt;

&lt;h2&gt;5. Engineering Significance&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Used in spiral columns and circular piles&lt;/li&gt;
&lt;li&gt;Provides confinement to concrete&lt;/li&gt;
&lt;li&gt;Improves ductility and strength&lt;/li&gt;
&lt;li&gt;Essential for seismic-resistant structures&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;6. Practical Applications&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;RCC circular columns&lt;/li&gt;
&lt;li&gt;Bored cast-in-situ piles&lt;/li&gt;
&lt;li&gt;Bridge piers&lt;/li&gt;
&lt;li&gt;Chimneys and silos&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;7. Assumptions&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Uniform pitch throughout height&lt;/li&gt;
&lt;li&gt;Perfect circular geometry&lt;/li&gt;
&lt;li&gt;No allowance for hooks or laps&lt;/li&gt;
&lt;li&gt;Centerline diameter is used&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;8. Limitations&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No code-based spacing checks (IS 456 / IS 2911)&lt;/li&gt;
&lt;li&gt;No confinement ratio calculation&lt;/li&gt;
&lt;li&gt;No detailing for anchorage or laps&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;9. Workflow Summary&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;User inputs height, diameter, and pitch&lt;/li&gt;
&lt;li&gt;Tool calculates number of turns&lt;/li&gt;
&lt;li&gt;Length of one turn is computed&lt;/li&gt;
&lt;li&gt;Total reinforcement length is displayed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;10. Conclusion&lt;/h2&gt;

&lt;p&gt;
This tool acts as a &lt;span class=&quot;highlight&quot;&gt;quick and accurate helical reinforcement calculator&lt;/span&gt;,
helping engineers and site professionals prepare bar bending schedules efficiently.
&lt;/p&gt;

&lt;p&gt;
For final design, additional checks such as spacing limits, anchorage,
and code compliance should be considered.
&lt;/p&gt;

&lt;/div&gt;

    &lt;script&gt;
        function calcHelical() {
            const H = parseFloat(document.getElementById(&#39;h_height&#39;).value);
            const D = parseFloat(document.getElementById(&#39;h_dia&#39;).value);
            const P = parseFloat(document.getElementById(&#39;h_pitch&#39;).value);
            const resBox = document.getElementById(&#39;h-result-box&#39;);

            if (!H || !D || !P) {
                alert(&quot;Please enter all dimensions in meters.&quot;);
                return;
            }

            // 1. Number of turns
            const n = H / P;
            
            // 2. Circumference (C = π * D)
            const C = Math.PI * D;
            
            // 3. Length of one turn (Hypotenuse of C and P)
            // L_turn = sqrt(C^2 + P^2)
            const oneTurnLen = Math.sqrt(Math.pow(C, 2) + Math.pow(P, 2));
            
            // 4. Total length
            const totalLen = n * oneTurnLen;

            // Display results
            resBox.style.display = &#39;block&#39;;
            document.getElementById(&#39;out_turns&#39;).innerText = n.toFixed(2);
            document.getElementById(&#39;out_len&#39;).innerText = totalLen.toFixed(3) + &quot; meters&quot;;
        }
    &lt;/script&gt;

&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/03/helical-ring-length-calculator_01175476092.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-775496378427670248</guid><pubDate>Tue, 17 Mar 2026 09:01:03 +0000</pubDate><atom:updated>2026-04-06T12:30:08.196+05:30</atom:updated><title>Invoice Calculations Verification</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;PWD Infrastructure - Monthly Bill Manager&lt;/title&gt;
    &lt;style&gt;
        body { font-family: &#39;Segoe UI&#39;, Arial, sans-serif; background-color: #f0f2f5; padding: 20px; }
        .container { max-width: 1200px; margin: auto; background: #fff; padding: 20px; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
        h2 { color: #1a73e8; border-bottom: 3px solid #1a73e8; padding-bottom: 10px; margin-top: 0; }
        
        .config-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; margin-bottom: 20px; background: #e8f0fe; padding: 15px; border-radius: 8px; border: 1px solid #1a73e8; }
        .header-grid { display: grid; grid-template-columns: 1.5fr 0.8fr 1.2fr 1fr; gap: 15px; margin-bottom: 20px; background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 5px solid #1a73e8; }
        
        .action-bar { display: flex; gap: 10px; margin-bottom: 20px; background: #fff; padding: 10px; border: 1px dashed #ccc; border-radius: 8px; }
        .btn-action { padding: 8px 15px; border: none; border-radius: 4px; cursor: pointer; font-weight: 600; font-size: 0.8rem; transition: 0.2s; }
        .btn-export { background: #673ab7; color: white; }
        .btn-import { background: #ff9800; color: white; }
        .btn-edit { background: #00bcd4; color: white; }

        .field label { display: block; font-weight: bold; margin-bottom: 5px; color: #5f6368; font-size: 0.75rem; text-transform: uppercase; }
        input { padding: 8px; border: 1px solid #dadce0; border-radius: 4px; width: 100%; box-sizing: border-box; font-size: 14px; font-weight: 600; }
        .auto-field { background-color: #e6fffa; border: 1px solid #38b2ac; color: #2c7a7b; }

        table { width: 100%; border-collapse: collapse; margin-top: 10px; }
        th { background-color: #3c4043; color: white; padding: 8px; font-size: 0.85rem; }
        td { border: 1px solid #dee2e6; padding: 6px; }
        .num { text-align: right; font-family: &#39;Consolas&#39;, monospace; }

        .footer-row { background-color: #f8f9fa; font-weight: bold; }
        .deduction { color: #d93025; }
        .net-payable { background-color: #1a73e8; color: white; font-size: 1.15rem; }

        .alert { color: #d93025; font-weight: bold; background: #fce8e6; padding: 10px; border-radius: 4px; display: none; margin-top: 15px; text-align: center; border: 1px solid #d93025; }
        .btn-save { padding: 15px 30px; border: none; border-radius: 6px; cursor: pointer; font-weight: 700; background-color: #1e8e3e; color: white; margin-top: 20px; width: 100%; font-size: 1rem; }
        .btn-save:disabled { background-color: #ccc; cursor: not-allowed; }
        
        .history-section { margin-top: 30px; border-top: 2px solid #eee; padding-top: 20px; }
        .btn-small { padding: 4px 8px; font-size: 11px; margin-left: 5px; cursor: pointer; }
      h1, h2 {
    color: #0b3d91;
}
h2 {
    border-left: 5px solid #007bff;
    padding-left: 10px;
}
ul {
    margin-left: 20px;
}
.code {
    background: #f8f9fa;
    padding: 10px;
    border-left: 4px solid #007bff;
    font-family: monospace;
}
.highlight {
    color: #d62828;
    font-weight: bold;
}
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;container&quot;&gt;
    &lt;h2&gt;Road Project Bill Verification&lt;/h2&gt;

    &lt;div class=&quot;action-bar&quot;&gt;
        &lt;button class=&quot;btn-action btn-export&quot; onclick=&quot;exportJSON()&quot;&gt;💾 Export JSON Data&lt;/button&gt;
        &lt;button class=&quot;btn-action btn-import&quot; onclick=&quot;document.getElementById(&#39;importFile&#39;).click()&quot;&gt;📂 Import JSON&lt;/button&gt;
        &lt;input type=&quot;file&quot; id=&quot;importFile&quot; style=&quot;display:none&quot; onchange=&quot;importJSON(event)&quot;&gt;
        &lt;button class=&quot;btn-action btn-edit&quot; onclick=&quot;scrollToHistory()&quot;&gt;📋 View/Edit History&lt;/button&gt;
    &lt;/div&gt;
    
   
        &lt;div class=&quot;field&quot;&gt;&lt;label&gt;Project Cost (₹)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;totalProjectCost&quot; value=&quot;74225000&quot; oninput=&quot;calc()&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;field&quot;&gt;&lt;label&gt;Allocation (%)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;allocPercent&quot; value=&quot;100&quot; step=&quot;0.01&quot; oninput=&quot;calc()&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;field&quot;&gt;&lt;label&gt;Negotiation (%)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;negPercent&quot; value=&quot;4.59&quot; step=&quot;0.01&quot; oninput=&quot;calc()&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;field&quot;&gt;&lt;label&gt;GST Rate (%)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;gstPercent&quot; value=&quot;18&quot; oninput=&quot;calc()&quot;&gt;&lt;/div&gt;
    

   
        &lt;div class=&quot;field&quot;&gt;&lt;label&gt;Project Name&lt;/label&gt;&lt;input list=&quot;projectList&quot; id=&quot;projName&quot; value=&quot;Sinhasth Kumbh Pkg -C&quot; onchange=&quot;syncHistory()&quot;&gt;&lt;datalist id=&quot;projectList&quot;&gt;&lt;/datalist&gt;&lt;/div&gt;
        &lt;div class=&quot;field&quot;&gt;&lt;label&gt;Bill No.&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;billNo&quot; value=&quot;1&quot; class=&quot;auto-field&quot; readonly&gt;&lt;/div&gt;
        &lt;div class=&quot;field&quot;&gt;&lt;label&gt;Cumulative Prev. Paid&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;prevPaid&quot; class=&quot;auto-field&quot; readonly value=&quot;0&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;field&quot;&gt;&lt;label&gt;Budget Limit (₹)&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;budgetLimit&quot; readonly class=&quot;auto-field&quot;&gt;&lt;/div&gt;
    

    &lt;table&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th style=&quot;text-align: left;&quot;&gt;Item Description&lt;/th&gt;
                &lt;th style=&quot;width: 20%;&quot;&gt;Contract (₹)&lt;/th&gt;
                &lt;th style=&quot;width: 20%;&quot;&gt;This Month (₹)&lt;/th&gt;
                &lt;th style=&quot;width: 20%;&quot;&gt;Remaining Balance&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody id=&quot;billItems&quot;&gt;&lt;/tbody&gt;
        &lt;tfoot&gt;
            &lt;tr class=&quot;footer-row&quot;&gt;
                &lt;td colspan=&quot;2&quot;&gt;1. Sub-Total Amount (Gross)&lt;/td&gt;
                &lt;td id=&quot;subTotal&quot; class=&quot;num&quot;&gt;0.00&lt;/td&gt;
                &lt;td&gt;-&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td colspan=&quot;2&quot;&gt;2. Negotiation Amount (&lt;span id=&quot;negLab&quot;&gt;4.59&lt;/span&gt;%) [Deduction]&lt;/td&gt;
                &lt;td id=&quot;negAmt&quot; class=&quot;num deduction&quot;&gt;- 0.00&lt;/td&gt;
                &lt;td&gt;-&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr class=&quot;footer-row&quot;&gt;
                &lt;td colspan=&quot;2&quot;&gt;3. Final Total Amount (Excl. GST)&lt;/td&gt;
                &lt;td id=&quot;finalTotalExcl&quot; class=&quot;num&quot;&gt;0.00&lt;/td&gt;
                &lt;td&gt;-&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td colspan=&quot;2&quot;&gt;4. GST Amount (&lt;span id=&quot;gstLab&quot;&gt;18&lt;/span&gt;%) on Final Total&lt;/td&gt;
                &lt;td id=&quot;gstAmt&quot; class=&quot;num&quot;&gt;+ 0.00&lt;/td&gt;
                &lt;td&gt;-&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr class=&quot;net-payable&quot;&gt;
                &lt;td colspan=&quot;2&quot;&gt;NET PAYABLE AMOUNT (FOR BILL NO. &lt;span id=&quot;dispBillNo&quot;&gt;1&lt;/span&gt;)&lt;/td&gt;
                &lt;td id=&quot;netPayable&quot; class=&quot;num&quot;&gt;₹ 0.00&lt;/td&gt;
                &lt;td&gt;-&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tfoot&gt;
    &lt;/table&gt;

    &lt;div id=&quot;budgetWarning&quot; class=&quot;alert&quot;&gt;⚠️ BUDGET EXCEEDED: Sum of all bills exceeds the allotted project funds!&lt;/div&gt;
    &lt;button id=&quot;saveBtn&quot; class=&quot;btn-save&quot; onclick=&quot;saveRecord()&quot;&gt;Submit &amp; Save Monthly Bill&lt;/button&gt;

    &lt;div class=&quot;history-section&quot; id=&quot;historySection&quot;&gt;
        &lt;h3&gt;Project History &amp; Edit Options&lt;/h3&gt;
        &lt;table id=&quot;historyTable&quot;&gt;
            &lt;thead&gt;
                &lt;tr&gt;
                    &lt;th&gt;Date&lt;/th&gt;
                    &lt;th&gt;Project&lt;/th&gt;
                    &lt;th&gt;Bill No&lt;/th&gt;
                    &lt;th&gt;Amount&lt;/th&gt;
                    &lt;th&gt;Actions&lt;/th&gt;
                &lt;/tr&gt;
            &lt;/thead&gt;
            &lt;tbody id=&quot;historyBody&quot;&gt;&lt;/tbody&gt;
        &lt;/table&gt;
    &lt;/div&gt;
&lt;/div&gt;
  
  &lt;div class=&quot;container&quot;&gt;

&lt;h1&gt;Road Project Bill Verification System – Technical Explanation&lt;/h1&gt;

&lt;p&gt;
This application is designed for &lt;strong&gt;verification, tracking, and management of road project bills&lt;/strong&gt;.
It ensures financial control by calculating payable amounts, monitoring budget limits, and maintaining
a complete history of billing records using a structured digital workflow.
&lt;/p&gt;

&lt;h2&gt;1. Objective of the System&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Verify contractor bills against project budget&lt;/li&gt;
&lt;li&gt;Apply negotiation deductions and GST calculations&lt;/li&gt;
&lt;li&gt;Track cumulative payments&lt;/li&gt;
&lt;li&gt;Prevent budget overruns&lt;/li&gt;
&lt;li&gt;Maintain digital record of all bills&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;2. Input Parameters&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Project Cost:&lt;/strong&gt; Total sanctioned project value&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Allocation %:&lt;/strong&gt; Portion of budget allocated&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Negotiation %:&lt;/strong&gt; Agreed deduction percentage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GST %:&lt;/strong&gt; Applicable tax rate&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project Name:&lt;/strong&gt; Identifier for tracking&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bill No:&lt;/strong&gt; Auto-generated sequence&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;3. Bill Item Structure&lt;/h2&gt;

&lt;p&gt;
The system includes predefined cost heads:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Professional Staff&lt;/li&gt;
&lt;li&gt;Supporting Staff&lt;/li&gt;
&lt;li&gt;Transportation&lt;/li&gt;
&lt;li&gt;Office Expenses&lt;/li&gt;
&lt;li&gt;Training &amp; Contingencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Each item includes:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Contract Value&lt;/li&gt;
&lt;li&gt;Current Bill Amount&lt;/li&gt;
&lt;li&gt;Remaining Balance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;4. Financial Calculation Logic&lt;/h2&gt;

&lt;h3&gt;4.1 Sub-Total (Gross Amount)&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
SubTotal = Σ(Current Bill Amounts)
&lt;/div&gt;

&lt;h3&gt;4.2 Negotiation Deduction&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Negotiation Amount = SubTotal × (Negotiation %)
&lt;/div&gt;

&lt;h3&gt;4.3 Final Amount (Excluding GST)&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Final Amount = SubTotal - Negotiation Amount
&lt;/div&gt;

&lt;h3&gt;4.4 GST Calculation&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
GST Amount = Final Amount × (GST %)
&lt;/div&gt;

&lt;h3&gt;4.5 Net Payable Amount&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Net Payable = Final Amount + GST
&lt;/div&gt;

&lt;p&gt;
This represents the total amount payable for the current bill.
&lt;/p&gt;

&lt;h2&gt;5. Budget Control Mechanism&lt;/h2&gt;

&lt;h3&gt;5.1 Budget Limit&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Budget Limit = Project Cost × Allocation %
&lt;/div&gt;

&lt;h3&gt;5.2 Total Liability Check&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
Total Liability = Previous Paid + Current Bill Amount
&lt;/div&gt;

&lt;p&gt;
If:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Total Liability &gt; Budget Limit → Warning Triggered
&lt;/div&gt;

&lt;p class=&quot;highlight&quot;&gt;
System disables saving when budget is exceeded.
&lt;/p&gt;

&lt;h2&gt;6. Data Storage (IndexedDB)&lt;/h2&gt;

&lt;p&gt;
All billing records are stored in browser database:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
indexedDB → &quot;PWD_Final_Bills&quot;
&lt;/div&gt;

&lt;p&gt;
Each record contains:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project name&lt;/li&gt;
&lt;li&gt;Bill number&lt;/li&gt;
&lt;li&gt;Net payable amount&lt;/li&gt;
&lt;li&gt;Item-wise data&lt;/li&gt;
&lt;li&gt;Configuration (GST, negotiation, etc.)&lt;/li&gt;
&lt;li&gt;Timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;7. History &amp; Editing System&lt;/h2&gt;

&lt;p&gt;
The system maintains a full history of bills:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-increment bill numbers&lt;/li&gt;
&lt;li&gt;View previous records&lt;/li&gt;
&lt;li&gt;Edit/load existing entries&lt;/li&gt;
&lt;li&gt;Delete unwanted records&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;code&quot;&gt;
store.getAll() → Filter by project → Render table
&lt;/div&gt;

&lt;h2&gt;8. Import / Export Feature&lt;/h2&gt;

&lt;h3&gt;8.1 Export&lt;/h3&gt;

&lt;p&gt;
Data can be downloaded as JSON:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
JSON.stringify(records)
&lt;/div&gt;

&lt;h3&gt;8.2 Import&lt;/h3&gt;

&lt;p&gt;
Backup files can be restored into the system:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File is read using FileReader&lt;/li&gt;
&lt;li&gt;Records inserted into IndexedDB&lt;/li&gt;
&lt;li&gt;IDs regenerated automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;9. Workflow Summary&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;User enters project and bill details&lt;/li&gt;
&lt;li&gt;Inputs current bill amounts&lt;/li&gt;
&lt;li&gt;System calculates totals and deductions&lt;/li&gt;
&lt;li&gt;Budget validation is performed&lt;/li&gt;
&lt;li&gt;Bill is saved if within limit&lt;/li&gt;
&lt;li&gt;History is updated automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;10. Engineering &amp; Administrative Benefits&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prevents financial mismanagement&lt;/li&gt;
&lt;li&gt;Ensures transparency in billing&lt;/li&gt;
&lt;li&gt;Reduces manual calculation errors&lt;/li&gt;
&lt;li&gt;Provides quick audit trail&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;11. Assumptions&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All costs are inclusive of contract conditions&lt;/li&gt;
&lt;li&gt;Negotiation applies uniformly across items&lt;/li&gt;
&lt;li&gt;GST is applied on final amount only&lt;/li&gt;
&lt;li&gt;No escalation or variation considered&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;12. Limitations&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No multi-user synchronization&lt;/li&gt;
&lt;li&gt;No backend database (client-side only)&lt;/li&gt;
&lt;li&gt;No approval workflow&lt;/li&gt;
&lt;li&gt;No integration with accounting systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;13. Conclusion&lt;/h2&gt;

&lt;p&gt;
This system acts as a &lt;span class=&quot;highlight&quot;&gt;digital bill verification and control tool&lt;/span&gt;
for infrastructure projects. It combines financial accuracy with ease of use,
making it highly suitable for engineers, auditors, and project managers.
&lt;/p&gt;

&lt;p&gt;
For advanced deployment, the system can be extended with cloud databases,
user authentication, and integration with ERP systems.
&lt;/p&gt;

&lt;/div&gt;

&lt;script&gt;
    const lineItems = [
        [&quot;I. Professional Staff&quot;, 45975000], [&quot;II. Supporting Staff&quot;, 7650000],
        [&quot;III. Transportation&quot;, 5430000], [&quot;IV. Duty Travel&quot;, 200000],
        [&quot;V. Office Rent&quot;, 2700000], [&quot;VI. Office Supplies&quot;, 900000],
        [&quot;VII. Office Furniture&quot;, 810000], [&quot;VIII. Reports &amp; Printing&quot;, 1160000],
        [&quot;X. Training Costs&quot;, 100000], [&quot;XI. Contingencies&quot;, 1000000]
    ];

    const tbody = document.getElementById(&#39;billItems&#39;);
    lineItems.forEach((item, idx) =&gt; {
        tbody.innerHTML += `&lt;tr&gt;&lt;td&gt;${item[0]}&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;number&quot; class=&quot;num contract-val&quot; value=&quot;${item[1]}&quot; oninput=&quot;calc()&quot;&gt;&lt;/td&gt;
            &lt;td&gt;&lt;input type=&quot;number&quot; class=&quot;num current-val&quot; value=&quot;0&quot; oninput=&quot;calc()&quot;&gt;&lt;/td&gt;
            &lt;td class=&quot;num rem-val&quot; style=&quot;color: #666;&quot;&gt;0.00&lt;/td&gt;&lt;/tr&gt;`;
    });

    let db;
    const dbReq = indexedDB.open(&quot;PWD_Final_Bills&quot;, 2);
    dbReq.onupgradeneeded = (e) =&gt; {
        db = e.target.result;
        if(!db.objectStoreNames.contains(&quot;bills&quot;)) {
            db.createObjectStore(&quot;bills&quot;, { keyPath: &quot;id&quot;, autoIncrement: true });
        }
    };
    dbReq.onsuccess = (e) =&gt; { db = e.target.result; updateDatalist(); syncHistory(); };

    function syncHistory() {
        const proj = document.getElementById(&#39;projName&#39;).value;
        const tx = db.transaction(&quot;bills&quot;, &quot;readonly&quot;);
        const store = tx.objectStore(&quot;bills&quot;);
        store.getAll().onsuccess = (e) =&gt; {
            const allRecords = e.target.result;
            const history = allRecords.filter(r =&gt; r.project === proj);
            const lastNo = history.length &gt; 0 ? Math.max(...history.map(r =&gt; r.billNo)) : 0;
            
            document.getElementById(&#39;billNo&#39;).value = lastNo + 1;
            document.getElementById(&#39;dispBillNo&#39;).innerHTML = lastNo + 1;
            document.getElementById(&#39;prevPaid&#39;).value = history.reduce((sum, r) =&gt; sum + r.netAmount, 0).toFixed(2);
            
            renderHistoryTable(allRecords);
            calc();
        };
    }

    function calc() {
        const limit = (parseFloat(document.getElementById(&#39;totalProjectCost&#39;).value) || 0) * ((parseFloat(document.getElementById(&#39;allocPercent&#39;).value) || 0) / 100);
        document.getElementById(&#39;budgetLimit&#39;).value = &quot;₹ &quot; + limit.toLocaleString(&#39;en-IN&#39;);

        let subTotal = 0;
        document.querySelectorAll(&quot;#billItems tr&quot;).forEach(row =&gt; {
            const cont = parseFloat(row.querySelector(&quot;.contract-val&quot;).value) || 0;
            const curr = parseFloat(row.querySelector(&quot;.current-val&quot;).value) || 0;
            row.querySelector(&quot;.rem-val&quot;).innerHTML = (cont - curr).toLocaleString(&#39;en-IN&#39;);
            subTotal += curr;
        });

        const negRate = (parseFloat(document.getElementById(&#39;negPercent&#39;).value) || 0) / 100;
        const gstRate = (parseFloat(document.getElementById(&#39;gstPercent&#39;).value) || 0) / 100;
        
        const negAmt = subTotal * negRate;
        const finalExcl = subTotal - negAmt;
        const gstAmt = finalExcl * gstRate;
        const netPayable = finalExcl + gstAmt;

        document.getElementById(&#39;negLab&#39;).innerHTML = (negRate * 100).toFixed(2);
        document.getElementById(&#39;gstLab&#39;).innerHTML = (gstRate * 100).toFixed(0);
        document.getElementById(&#39;subTotal&#39;).innerHTML = subTotal.toLocaleString(&#39;en-IN&#39;, {minimumFractionDigits: 2});
        document.getElementById(&#39;negAmt&#39;).innerHTML = &quot;- &quot; + negAmt.toLocaleString(&#39;en-IN&#39;, {minimumFractionDigits: 2});
        document.getElementById(&#39;finalTotalExcl&#39;).innerHTML = finalExcl.toLocaleString(&#39;en-IN&#39;, {minimumFractionDigits: 2});
        document.getElementById(&#39;gstAmt&#39;).innerHTML = &quot;+ &quot; + gstAmt.toLocaleString(&#39;en-IN&#39;, {minimumFractionDigits: 2});
        document.getElementById(&#39;netPayable&#39;).innerHTML = &quot;₹ &quot; + netPayable.toLocaleString(&#39;en-IN&#39;, {minimumFractionDigits: 2});

        const totalLiability = (parseFloat(document.getElementById(&#39;prevPaid&#39;).value) || 0) + netPayable;
        const warn = document.getElementById(&#39;budgetWarning&#39;);
        const saveBtn = document.getElementById(&#39;saveBtn&#39;);
        
        const isOverBudget = totalLiability &gt; limit;
        warn.style.display = isOverBudget ? &quot;block&quot; : &quot;none&quot;;
        saveBtn.disabled = isOverBudget;
        window.currentNet = netPayable;
    }

    function saveRecord() {
        const tx = db.transaction(&quot;bills&quot;, &quot;readwrite&quot;);
        // Capture current state of inputs to allow for &quot;editing&quot; later
        const currentInputs = Array.from(document.querySelectorAll(&#39;.current-val&#39;)).map(i =&gt; i.value);
        const contractInputs = Array.from(document.querySelectorAll(&#39;.contract-val&#39;)).map(i =&gt; i.value);

        const entry = {
            project: document.getElementById(&#39;projName&#39;).value,
            billNo: parseInt(document.getElementById(&#39;billNo&#39;).value),
            netAmount: window.currentNet,
            config: {
                totalCost: document.getElementById(&#39;totalProjectCost&#39;).value,
                neg: document.getElementById(&#39;negPercent&#39;).value,
                gst: document.getElementById(&#39;gstPercent&#39;).value,
                alloc: document.getElementById(&#39;allocPercent&#39;).value
            },
            items: currentInputs,
            contracts: contractInputs,
            timestamp: new Date().toLocaleString()
        };
        tx.objectStore(&quot;bills&quot;).add(entry).onsuccess = () =&gt; {
            alert(`Successfully Saved Bill No. ${entry.billNo}`);
            updateDatalist();
            syncHistory();
        };
    }

    function renderHistoryTable(records) {
        const hBody = document.getElementById(&#39;historyBody&#39;);
        hBody.innerHTML = records.map(r =&gt; `
            &lt;tr&gt;
                &lt;td&gt;${r.timestamp}&lt;/td&gt;
                &lt;td&gt;${r.project}&lt;/td&gt;
                &lt;td&gt;${r.billNo}&lt;/td&gt;
                &lt;td&gt;₹${r.netAmount.toLocaleString(&#39;en-IN&#39;)}&lt;/td&gt;
                &lt;td&gt;
                    &lt;button class=&quot;btn-small&quot; style=&quot;background:#00bcd4; color:white;&quot; onclick=&#39;loadRecord(${JSON.stringify(r)})&#39;&gt;Edit/Load&lt;/button&gt;
                    &lt;button class=&quot;btn-small&quot; style=&quot;background:#f44336; color:white;&quot; onclick=&quot;deleteRecord(${r.id})&quot;&gt;Del&lt;/button&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        `).join(&#39;&#39;);
    }

    function loadRecord(record) {
        if(!confirm(&quot;Load this record? Current unsaved changes will be lost.&quot;)) return;
        document.getElementById(&#39;projName&#39;).value = record.project;
        document.getElementById(&#39;totalProjectCost&#39;).value = record.config.totalCost;
        document.getElementById(&#39;negPercent&#39;).value = record.config.neg;
        document.getElementById(&#39;gstPercent&#39;).value = record.config.gst;
        document.getElementById(&#39;allocPercent&#39;).value = record.config.alloc;
        
        const currentInputs = document.querySelectorAll(&#39;.current-val&#39;);
        const contractInputs = document.querySelectorAll(&#39;.contract-val&#39;);
        
        record.items.forEach((val, i) =&gt; currentInputs[i].value = val);
        record.contracts.forEach((val, i) =&gt; contractInputs[i].value = val);
        
        calc();
        window.scrollTo(0,0);
    }

    function deleteRecord(id) {
        if(confirm(&quot;Permanently delete this record?&quot;)) {
            const tx = db.transaction(&quot;bills&quot;, &quot;readwrite&quot;);
            tx.objectStore(&quot;bills&quot;).delete(id).onsuccess = () =&gt; syncHistory();
        }
    }

    function exportJSON() {
        const tx = db.transaction(&quot;bills&quot;, &quot;readonly&quot;);
        tx.objectStore(&quot;bills&quot;).getAll().onsuccess = (e) =&gt; {
            const dataStr = &quot;data:text/json;charset=utf-8,&quot; + encodeURIComponent(JSON.stringify(e.target.result));
            const downloadAnchorNode = document.createElement(&#39;a&#39;);
            downloadAnchorNode.setAttribute(&quot;href&quot;, dataStr);
            downloadAnchorNode.setAttribute(&quot;download&quot;, &quot;pwd_billing_backup.json&quot;);
            document.body.appendChild(downloadAnchorNode);
            downloadAnchorNode.click();
            downloadAnchorNode.remove();
        };
    }

    function importJSON(event) {
        const file = event.target.files[0];
        if (!file) return;
        const reader = new FileReader();
        reader.onload = (e) =&gt; {
            const data = JSON.parse(e.target.result);
            const tx = db.transaction(&quot;bills&quot;, &quot;readwrite&quot;);
            const store = tx.objectStore(&quot;bills&quot;);
            data.forEach(item =&gt; {
                delete item.id; // Allow IndexedDB to generate new IDs
                store.add(item);
            });
            tx.oncomplete = () =&gt; {
                alert(&quot;Import Successful!&quot;);
                syncHistory();
                updateDatalist();
            };
        };
        reader.readAsText(file);
    }

    function updateDatalist() {
        const tx = db.transaction(&quot;bills&quot;, &quot;readonly&quot;);
        tx.objectStore(&quot;bills&quot;).getAll().onsuccess = (e) =&gt; {
            const projects = [...new Set(e.target.result.map(r =&gt; r.project))];
            document.getElementById(&#39;projectList&#39;).innerHTML = projects.map(p =&gt; `&lt;option value=&quot;${p}&quot;&gt;`).join(&#39;&#39;);
        };
    }

    function scrollToHistory() {
        document.getElementById(&#39;historySection&#39;).scrollIntoView({behavior: &#39;smooth&#39;});
    }
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/03/invoice-calculations-verification.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1074964965522467583.post-7864331520127220443</guid><pubDate>Tue, 17 Mar 2026 07:56:48 +0000</pubDate><atom:updated>2026-04-06T12:33:04.615+05:30</atom:updated><category domain="http://www.blogger.com/atom/ns#">PWD Working</category><title>Expenditure Tracker</title><description>&lt;div id=&quot;pwd-tracker-root&quot;&gt;
&lt;style&gt;
    /* Scoping everything to #pwd-tracker-root to prevent clashing with Blogger Theme */
    #pwd-tracker-root {
        --primary: #2563eb;
        --success: #10b981;
        --danger: #ef4444;
        --bg: #f8fafc;
        font-family: &#39;Segoe UI&#39;, Tahoma, Geneva, Verdana, sans-serif;
        background: var(--bg);
        padding: 10px;
        color: #1e293b;
        border-radius: 8px;
    }
    #pwd-tracker-root .container {
        max-width: 100%;
        margin: auto;
        background: white;
        padding: 15px;
        border-radius: 12px;
        box-shadow: 0 4px 15px rgba(0,0,0,0.1);
    }
    #pwd-tracker-root .section {
        margin-bottom: 25px;
        padding: 15px;
        border-radius: 8px;
        border: 1px solid #e2e8f0;
    }
    #pwd-tracker-root .master-ts { background: #fffcf0; border-color: #fde68a; }
    #pwd-tracker-root .ra-bill { border-left: 6px solid var(--primary); background: #fff; margin-bottom: 20px; }

    /* Blogger Mobile Responsive Fix */
    #pwd-tracker-root .scroll-wrapper {
        width: 100%;
        overflow-x: auto;
        margin-bottom: 15px;
        border: 1px solid #e2e8f0;
        background: #fff;
    }

    /* Fixed Header Grid for Blogger */
    #pwd-tracker-root .header-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
        gap: 15px;
        padding: 10px;
    }

    #pwd-tracker-root .bill-grid {
        display: grid;
        grid-template-columns: 250px 140px 140px 300px 60px;
        gap: 10px;
        padding: 10px;
        min-width: 900px;
        align-items: center;
    }

    #pwd-tracker-root .bill-header {
        background: #f1f5f9;
        font-weight: bold;
        font-size: 0.8em;
        text-transform: uppercase;
    }

    #pwd-tracker-root input, #pwd-tracker-root select {
        padding: 8px;
        border: 1px solid #cbd5e1;
        border-radius: 4px;
        width: 100%;
        box-sizing: border-box;
    }

    #pwd-tracker-root label {
        font-size: 0.75em;
        font-weight: 700;
        color: #64748b;
        display: block;
        margin-bottom: 4px;
    }

    #pwd-tracker-root .btn {
        padding: 8px 16px;
        border: none;
        border-radius: 6px;
        cursor: pointer;
        font-weight: 600;
        transition: 0.2s;
    }
    #pwd-tracker-root .btn-add { background: var(--success); color: white; }
    #pwd-tracker-root .btn-bill { background: var(--primary); color: white; }
    #pwd-tracker-root .btn-save { background: #1e293b; color: white; width: 100%; margin-top: 10px; padding: 12px; }
    #pwd-tracker-root .btn-del { background: var(--danger); color: white; padding: 4px 8px; font-size: 11px; }

    #pwd-tracker-root .summary-table {
        width: 100%;
        border-collapse: collapse;
        min-width: 800px;
    }
    #pwd-tracker-root .summary-table th, #pwd-tracker-root .summary-table td {
        border: 1px solid #e2e8f0;
        padding: 10px;
        text-align: left;
        font-size: 13px;
    }
    #pwd-tracker-root .status-pill {
        padding: 3px 8px;
        border-radius: 12px;
        font-size: 10px;
        font-weight: bold;
    }
    #pwd-tracker-root .pill-ok { background: #dcfce7; color: #166534; }
    #pwd-tracker-root .pill-error { background: #fee2e2; color: #991b1b; }
  h1, h2 {
    color: #1e3a8a;
}
h2 {
    border-left: 5px solid #2563eb;
    padding-left: 10px;
}
ul {
    margin-left: 20px;
}
.code {
    background: #f8f9fa;
    padding: 10px;
    border-left: 4px solid #2563eb;
    font-family: monospace;
}
.highlight {
    color: #dc2626;
    font-weight: bold;
}
&lt;/style&gt;

&lt;div class=&quot;container&quot;&gt;
    &lt;h2 style=&quot;text-align:center; color: #2563eb;&quot;&gt;Infrastructure Project Dashboard&lt;/h2&gt;
  
  &lt;div class=&quot;section&quot; style=&quot;background: #f8fafc; border: 1px dashed #cbd5e1; display: flex; gap: 10px; justify-content: center;&quot;&gt;
    &lt;button class=&quot;btn&quot; style=&quot;background: #059669;&quot; onclick=&quot;exportProjectJSON()&quot;&gt;📤 Export Backup (JSON)&lt;/button&gt;
    &lt;button class=&quot;btn&quot; style=&quot;background: #7c3aed;&quot; onclick=&quot;triggerImport()&quot;&gt;📥 Import Backup (JSON)&lt;/button&gt;
    &lt;input type=&quot;file&quot; id=&quot;importFile&quot; style=&quot;display:none&quot; accept=&quot;.json&quot; onchange=&quot;importProjectJSON(event)&quot;&gt;
&lt;/div&gt;

    &lt;div class=&quot;section&quot;&gt;
        &lt;h3&gt;General Project Information&lt;/h3&gt;
        &lt;div class=&quot;header-grid&quot;&gt;
            &lt;div style=&quot;grid-column: span 2;&quot;&gt;&lt;label&gt;Project Name&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;projName&quot; placeholder=&quot;Enter Full Name of Work&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;Work Code / Job No.&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;workCode&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;Division&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;division&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;header-grid&quot;&gt;
            &lt;div&gt;&lt;label&gt;Admin Approval (AA) (₹)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;adminAmt&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;AA Ref No. &amp; Date&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;aaRef&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;Technical Sanction (TS) (₹)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;totalTS&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;TS Ref No. &amp; Date&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;tsRef&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;header-grid&quot;&gt;
            &lt;div&gt;&lt;label&gt;Tendered Amount (₹)&lt;/label&gt;&lt;input type=&quot;number&quot; id=&quot;tenderAmt&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;Contractor Name&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;contractor&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;Commencement Date&lt;/label&gt;&lt;input type=&quot;date&quot; id=&quot;startDate&quot;&gt;&lt;/div&gt;
            &lt;div&gt;&lt;label&gt;Stipulated Completion&lt;/label&gt;&lt;input type=&quot;date&quot; id=&quot;endDate&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;section master-ts&quot;&gt;
        &lt;div style=&quot;display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;&quot;&gt;
            &lt;h3 style=&quot;margin:0;&quot;&gt;1. Master TS Components&lt;/h3&gt;
            &lt;button class=&quot;btn btn-add&quot; onclick=&quot;addMasterRow()&quot;&gt;+ Add Component&lt;/button&gt;
        &lt;/div&gt;
        &lt;div class=&quot;scroll-wrapper&quot;&gt;
            &lt;div class=&quot;bill-grid bill-header&quot; style=&quot;grid-template-columns: 2fr 1fr 80px; min-width: 500px;&quot;&gt;
                &lt;div&gt;Component Name&lt;/div&gt;&lt;div&gt;TS Amount (₹)&lt;/div&gt;&lt;div&gt;Action&lt;/div&gt;
            &lt;/div&gt;
            &lt;div id=&quot;master-list&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;section&quot;&gt;
        &lt;div style=&quot;display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;&quot;&gt;
            &lt;h3 style=&quot;margin:0;&quot;&gt;2. RA Bill Entries&lt;/h3&gt;
            &lt;button class=&quot;btn btn-bill&quot; onclick=&quot;addNewBill()&quot;&gt;+ New RA Bill&lt;/button&gt;
        &lt;/div&gt;
        &lt;div id=&quot;bills-container&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&quot;section&quot;&gt;
        &lt;h3&gt;3. Cumulative Summary&lt;/h3&gt;
        &lt;div class=&quot;scroll-wrapper&quot;&gt;
            &lt;table class=&quot;summary-table&quot;&gt;
                &lt;thead&gt;
                    &lt;tr&gt;
                        &lt;th&gt;Description&lt;/th&gt;
                        &lt;th&gt;TS Amount&lt;/th&gt;
                        &lt;th&gt;Expended&lt;/th&gt;
                        &lt;th&gt;Balance&lt;/th&gt;
                        &lt;th&gt;Status&lt;/th&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody id=&quot;summary-body&quot;&gt;&lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;button class=&quot;btn btn-save&quot; onclick=&quot;saveToDB()&quot;&gt;💾 Save Project Data &amp; Update Records&lt;/button&gt;
&lt;/div&gt;
  
&lt;div class=&quot;container&quot;&gt;

&lt;h1&gt;Infrastructure Project Dashboard – Technical Explanation&lt;/h1&gt;

&lt;p&gt;
This application is a &lt;strong&gt;comprehensive project monitoring and expenditure tracking system&lt;/strong&gt;
designed for infrastructure works. It integrates project data management, bill tracking, and
financial control into a single dashboard using browser-based storage.
&lt;/p&gt;

&lt;h2&gt;1. Objective of the System&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Manage project-level administrative and financial data&lt;/li&gt;
&lt;li&gt;Track Technical Sanction (TS) components&lt;/li&gt;
&lt;li&gt;Monitor RA (Running Account) bills&lt;/li&gt;
&lt;li&gt;Provide real-time expenditure vs budget comparison&lt;/li&gt;
&lt;li&gt;Enable backup and restoration of project data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;2. General Project Information&lt;/h2&gt;

&lt;p&gt;
The system captures key administrative details:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project Name, Work Code, Division&lt;/li&gt;
&lt;li&gt;Administrative Approval (AA)&lt;/li&gt;
&lt;li&gt;Technical Sanction (TS)&lt;/li&gt;
&lt;li&gt;Tendered Amount&lt;/li&gt;
&lt;li&gt;Contractor Details&lt;/li&gt;
&lt;li&gt;Project Timeline (Start &amp; Completion)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
These parameters form the base for financial and progress tracking.
&lt;/p&gt;

&lt;h2&gt;3. Master TS Components&lt;/h2&gt;

&lt;p&gt;
The project is divided into multiple components such as:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Civil Work&lt;/li&gt;
&lt;li&gt;Royalty&lt;/li&gt;
&lt;li&gt;Insurance&lt;/li&gt;
&lt;li&gt;Other custom components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Each component includes:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Component Name + TS Amount
&lt;/div&gt;

&lt;p&gt;
This defines the &lt;strong&gt;maximum allowable expenditure&lt;/strong&gt; for each category.
&lt;/p&gt;

&lt;h2&gt;4. RA Bill Management&lt;/h2&gt;

&lt;p&gt;
The system allows multiple RA bills, each containing:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bill Name (e.g., 1st RA, 2nd RA)&lt;/li&gt;
&lt;li&gt;Component-wise expenditure&lt;/li&gt;
&lt;li&gt;Remarks for each entry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Each bill dynamically links to master components:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Selected Component → Fetch TS Limit → Enter Current Amount
&lt;/div&gt;

&lt;h2&gt;5. Real-Time Synchronization Logic&lt;/h2&gt;

&lt;p&gt;
The core function &lt;strong&gt;syncAll()&lt;/strong&gt; performs:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updates dropdown options from master list&lt;/li&gt;
&lt;li&gt;Displays TS limits dynamically&lt;/li&gt;
&lt;li&gt;Aggregates expenditure across all bills&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;code&quot;&gt;
Total Expended = Σ (All RA Bills for each component)
&lt;/div&gt;

&lt;h2&gt;6. Cumulative Summary Calculation&lt;/h2&gt;

&lt;p&gt;
For each component:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Balance = TS Amount - Total Expended
&lt;/div&gt;

&lt;p&gt;
Status is determined as:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
If Balance &lt; 0 → OVER (Budget Exceeded)
Else → OK
&lt;/div&gt;

&lt;p class=&quot;highlight&quot;&gt;
Negative balance indicates overspending and requires immediate attention.
&lt;/p&gt;

&lt;h2&gt;7. Data Storage (IndexedDB)&lt;/h2&gt;

&lt;p&gt;
All project data is stored in browser database:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
Database: PWD_Blogger_DB  
Store: projects  
Key: id = &quot;p1&quot;
&lt;/div&gt;

&lt;p&gt;
Stored data includes:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project details&lt;/li&gt;
&lt;li&gt;Master components&lt;/li&gt;
&lt;li&gt;All RA bills&lt;/li&gt;
&lt;li&gt;Item-wise expenditure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;8. Save &amp; Load Mechanism&lt;/h2&gt;

&lt;h3&gt;Saving Data&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
objectStore.put(projectData)
&lt;/div&gt;

&lt;p&gt;
Ensures persistent storage within browser.
&lt;/p&gt;

&lt;h3&gt;Loading Data&lt;/h3&gt;

&lt;div class=&quot;code&quot;&gt;
objectStore.get(&quot;p1&quot;)
&lt;/div&gt;

&lt;p&gt;
Automatically restores previous session data.
&lt;/p&gt;

&lt;h2&gt;9. Import / Export Feature&lt;/h2&gt;

&lt;h3&gt;Export&lt;/h3&gt;

&lt;p&gt;
Project data is exported as JSON:
&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
JSON.stringify(data, null, 2)
&lt;/div&gt;

&lt;h3&gt;Import&lt;/h3&gt;

&lt;p&gt;
The system:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads JSON file&lt;/li&gt;
&lt;li&gt;Validates structure&lt;/li&gt;
&lt;li&gt;Saves to IndexedDB&lt;/li&gt;
&lt;li&gt;Reloads dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;10. Workflow Summary&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Enter project details&lt;/li&gt;
&lt;li&gt;Define TS components&lt;/li&gt;
&lt;li&gt;Add RA bills&lt;/li&gt;
&lt;li&gt;Input expenditure values&lt;/li&gt;
&lt;li&gt;System calculates totals and balances&lt;/li&gt;
&lt;li&gt;Monitor status (OK / OVER)&lt;/li&gt;
&lt;li&gt;Save data or export backup&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;11. Engineering &amp; Management Benefits&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Real-time budget monitoring&lt;/li&gt;
&lt;li&gt;Prevents overspending&lt;/li&gt;
&lt;li&gt;Centralized project tracking&lt;/li&gt;
&lt;li&gt;Improves transparency and accountability&lt;/li&gt;
&lt;li&gt;Reduces manual errors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;12. Assumptions&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All TS values are fixed and approved&lt;/li&gt;
&lt;li&gt;RA bills are cumulative in nature&lt;/li&gt;
&lt;li&gt;No variation orders considered&lt;/li&gt;
&lt;li&gt;Single-user environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;13. Limitations&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No cloud synchronization&lt;/li&gt;
&lt;li&gt;No multi-user collaboration&lt;/li&gt;
&lt;li&gt;No approval workflow&lt;/li&gt;
&lt;li&gt;No integration with accounting systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;14. Conclusion&lt;/h2&gt;

&lt;p&gt;
This dashboard functions as a &lt;span class=&quot;highlight&quot;&gt;powerful project expenditure tracking tool&lt;/span&gt;,
combining financial control with ease of use. It is especially useful for engineers,
project managers, and administrative authorities handling infrastructure works.
&lt;/p&gt;

&lt;p&gt;
Future enhancements may include cloud integration, real-time collaboration,
and advanced analytics dashboards.
&lt;/p&gt;

&lt;/div&gt;

&lt;script&gt;
    let db;
    let masterItems = [];

    // Initialize Database
    const request = indexedDB.open(&quot;PWD_Blogger_DB&quot;, 1);
    request.onupgradeneeded = e =&gt; {
        db = e.target.result;
        db.createObjectStore(&quot;projects&quot;, { keyPath: &quot;id&quot; });
    };
    request.onsuccess = e =&gt; { 
        db = e.target.result; 
        loadData(); 
    };

    function addMasterRow(name = &quot;&quot;, val = 0) {
        const id = &#39;m-&#39; + Date.now() + Math.random();
        const div = document.createElement(&#39;div&#39;);
        div.className = &#39;bill-grid&#39;;
        div.id = id;
        div.style.gridTemplateColumns = &quot;2fr 1fr 80px&quot;;
        div.style.minWidth = &quot;500px&quot;;
        div.innerHTML = `
            &lt;input type=&quot;text&quot; class=&quot;m-name&quot; value=&quot;${name}&quot; placeholder=&quot;Item Name&quot; oninput=&quot;syncAll()&quot;&gt;
            &lt;input type=&quot;number&quot; class=&quot;m-val&quot; value=&quot;${val}&quot; oninput=&quot;syncAll()&quot;&gt;
            &lt;button class=&quot;btn btn-del&quot; onclick=&quot;document.getElementById(&#39;${id}&#39;).remove(); syncAll();&quot;&gt;X&lt;/button&gt;
        `;
        document.getElementById(&#39;master-list&#39;).appendChild(div);
        syncAll();
    }

    function addNewBill(data = null) {
        const id = data ? data.id : &#39;bill-&#39; + Date.now();
        const div = document.createElement(&#39;div&#39;);
        div.className = &#39;section ra-bill&#39;;
        div.id = id;
        div.innerHTML = `
            &lt;div style=&quot;display:flex; justify-content:space-between; margin-bottom:10px;&quot;&gt;
                &lt;input type=&quot;text&quot; class=&quot;bill-no&quot; value=&quot;${data ? data.no : &#39;&#39;}&quot; placeholder=&quot;Bill Name (e.g. 1st RA)&quot; style=&quot;width:200px; font-weight:bold;&quot;&gt;
                &lt;button class=&quot;btn btn-del&quot; onclick=&quot;document.getElementById(&#39;${id}&#39;).remove(); syncAll();&quot;&gt;Delete Bill&lt;/button&gt;
            &lt;/div&gt;
            &lt;div class=&quot;scroll-wrapper&quot;&gt;
                &lt;div class=&quot;bill-grid bill-header&quot;&gt;
                    &lt;div&gt;Component&lt;/div&gt;&lt;div&gt;TS Limit&lt;/div&gt;&lt;div&gt;Current (₹)&lt;/div&gt;&lt;div&gt;Remarks&lt;/div&gt;&lt;div&gt;&lt;/div&gt;
                &lt;/div&gt;
                &lt;div id=&quot;rows-${id}&quot;&gt;&lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn btn-add&quot; style=&quot;font-size:11px; margin-top:5px;&quot; onclick=&quot;addItemToBill(&#39;${id}&#39;)&quot;&gt;+ Add Row&lt;/button&gt;
        `;
        document.getElementById(&#39;bills-container&#39;).prepend(div);
        if (data &amp;&amp; data.items) {
            data.items.forEach(i =&gt; addItemToBill(id, i.name, i.amt, i.remark));
        } else { addItemToBill(id); }
    }

    function addItemToBill(billId, sName = &quot;&quot;, amt = 0, remark = &quot;&quot;) {
        const div = document.createElement(&#39;div&#39;);
        div.className = &#39;bill-grid&#39;;
        let options = masterItems.map(m =&gt; `&lt;option value=&quot;${m.name}&quot; ${m.name === sName ? &#39;selected&#39; : &#39;&#39;}&gt;${m.name}&lt;/option&gt;`).join(&#39;&#39;);
        div.innerHTML = `
            &lt;select class=&quot;ra-sel&quot; onchange=&quot;syncAll()&quot;&gt;
                &lt;option value=&quot;&quot;&gt;-- Item --&lt;/option&gt;${options}
            &lt;/select&gt;
            &lt;div class=&quot;ts-disp&quot; style=&quot;font-weight:bold; color:var(--primary);&quot;&gt;0&lt;/div&gt;
            &lt;input type=&quot;number&quot; class=&quot;ra-amt&quot; value=&quot;${amt}&quot; oninput=&quot;syncAll()&quot;&gt;
            &lt;input type=&quot;text&quot; class=&quot;ra-rem&quot; value=&quot;${remark}&quot; placeholder=&quot;Notes&quot;&gt;
            &lt;button class=&quot;btn btn-del&quot; onclick=&quot;this.parentElement.remove(); syncAll();&quot;&gt;X&lt;/button&gt;
        `;
        document.getElementById(`rows-${billId}`).appendChild(div);
        syncAll();
    }

    function syncAll() {
        masterItems = Array.from(document.querySelectorAll(&#39;#master-list .bill-grid&#39;)).map(row =&gt; ({
            name: row.querySelector(&#39;.m-name&#39;).value,
            ts: parseFloat(row.querySelector(&#39;.m-val&#39;).value) || 0
        }));

        document.querySelectorAll(&#39;.ra-bill&#39;).forEach(bill =&gt; {
            bill.querySelectorAll(&#39;.bill-grid:not(.bill-header)&#39;).forEach(row =&gt; {
                const select = row.querySelector(&#39;.ra-sel&#39;);
                const cur = select.value;
                const tsDisp = row.querySelector(&#39;.ts-disp&#39;);
                select.innerHTML = `&lt;option value=&quot;&quot;&gt;-- Item --&lt;/option&gt;` + masterItems.map(m =&gt; `&lt;option value=&quot;${m.name}&quot; ${m.name === cur ? &#39;selected&#39; : &#39;&#39;}&gt;${m.name}&lt;/option&gt;`).join(&#39;&#39;);
                const match = masterItems.find(m =&gt; m.name === cur);
                tsDisp.innerHTML = match ? match.ts.toLocaleString(&#39;en-IN&#39;) : &quot;0&quot;;
            });
        });

        const totals = {};
        masterItems.forEach(m =&gt; totals[m.name] = { ts: m.ts, exp: 0 });
        document.querySelectorAll(&#39;.ra-bill .ra-amt&#39;).forEach(input =&gt; {
            const name = input.closest(&#39;.bill-grid&#39;).querySelector(&#39;.ra-sel&#39;).value;
            if (name &amp;&amp; totals[name]) totals[name].exp += parseFloat(input.value) || 0;
        });

        const tbody = document.getElementById(&#39;summary-body&#39;);
        tbody.innerHTML = &#39;&#39;;
        for (let name in totals) {
            const item = totals[name];
            const balance = item.ts - item.exp;
            tbody.innerHTML += `
                &lt;tr&gt;
                    &lt;td&gt;${name}&lt;/td&gt;
                    &lt;td&gt;${item.ts.toLocaleString(&#39;en-IN&#39;)}&lt;/td&gt;
                    &lt;td&gt;${item.exp.toLocaleString(&#39;en-IN&#39;)}&lt;/td&gt;
                    &lt;td style=&quot;color:${balance &lt; 0 ? &#39;red&#39; : &#39;green&#39;}; font-weight:bold;&quot;&gt;${balance.toLocaleString(&#39;en-IN&#39;)}&lt;/td&gt;
                    &lt;td&gt;&lt;span class=&quot;status-pill ${balance &lt; 0 ? &#39;pill-error&#39; : &#39;pill-ok&#39;}&quot;&gt;${balance &lt; 0 ? &#39;OVER&#39; : &#39;OK&#39;}&lt;/span&gt;&lt;/td&gt;
                &lt;/tr&gt;`;
        }
    }

    function saveToDB() {
        const fields = [&#39;projName&#39;, &#39;workCode&#39;, &#39;division&#39;, &#39;adminAmt&#39;, &#39;aaRef&#39;, &#39;totalTS&#39;, &#39;tsRef&#39;, &#39;tenderAmt&#39;, &#39;contractor&#39;, &#39;startDate&#39;, &#39;endDate&#39;];
        const data = { id: &quot;p1&quot; };
        fields.forEach(f =&gt; data[f] = document.getElementById(f).value);
        data.master = masterItems;
        data.bills = Array.from(document.querySelectorAll(&#39;.ra-bill&#39;)).map(b =&gt; ({
            id: b.id, no: b.querySelector(&#39;.bill-no&#39;).value,
            items: Array.from(b.querySelectorAll(&#39;.bill-grid:not(.bill-header)&#39;)).map(r =&gt; ({
                name: r.querySelector(&#39;.ra-sel&#39;).value, amt: r.querySelector(&#39;.ra-amt&#39;).value, remark: r.querySelector(&#39;.ra-rem&#39;).value
            }))
        }));
        const tx = db.transaction(&quot;projects&quot;, &quot;readwrite&quot;);
        tx.objectStore(&quot;projects&quot;).put(data);
        alert(&quot;Saved to browser memory!&quot;);
    }

    function loadData() {
        const tx = db.transaction(&quot;projects&quot;, &quot;readonly&quot;);
        const req = tx.objectStore(&quot;projects&quot;).get(&quot;p1&quot;);
        req.onsuccess = () =&gt; {
            const res = req.result;
            if (res) {
                const fields = [&#39;projName&#39;, &#39;workCode&#39;, &#39;division&#39;, &#39;adminAmt&#39;, &#39;aaRef&#39;, &#39;totalTS&#39;, &#39;tsRef&#39;, &#39;tenderAmt&#39;, &#39;contractor&#39;, &#39;startDate&#39;, &#39;endDate&#39;];
                fields.forEach(f =&gt; document.getElementById(f).value = res[f] || &quot;&quot;);
                res.master.forEach(m =&gt; addMasterRow(m.name, m.ts));
                res.bills.reverse().forEach(b =&gt; addNewBill(b));
                syncAll();
            } else { 
                [&quot;Civil Work&quot;, &quot;Royalty&quot;, &quot;Insurance&quot;].forEach(n =&gt; addMasterRow(n, 0)); 
            }
        };
    }
  
  function exportProjectJSON() {
        const tx = db.transaction(&quot;projects&quot;, &quot;readonly&quot;);
        const req = tx.objectStore(&quot;projects&quot;).get(&quot;p1&quot;);

        req.onsuccess = () =&gt; {
            const data = req.result;
            if (!data) {
                alert(&quot;No data found to export! Please save your project first.&quot;);
                return;
            }

            const date = new Date().toISOString().split(&#39;T&#39;)[0];
            const fileName = `Expenditure Tracker dated ${date}.json`;
            
            const blob = new Blob([JSON.stringify(data, null, 2)], { type: &quot;application/json&quot; });
            const url = URL.createObjectURL(blob);
            const a = document.createElement(&quot;a&quot;);
            
            a.href = url;
            a.download = fileName;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        };
    }
  
  function triggerImport() {
        document.getElementById(&#39;importFile&#39;).click();
    }

    // 3. New Import Function
    function importProjectJSON(event) {
        const file = event.target.files[0];
        if (!file) return;

        const reader = new FileReader();
        reader.onload = function(e) {
            try {
                const importedData = JSON.parse(e.target.result);
                
                // Validate if it&#39;s our project data
                if (!importedData.projName || !importedData.master) {
                    throw new Error(&quot;Invalid file format.&quot;);
                }

                // Save to IndexedDB
                const tx = db.transaction(&quot;projects&quot;, &quot;readwrite&quot;);
                const store = tx.objectStore(&quot;projects&quot;);
                store.put(importedData);

                tx.oncomplete = () =&gt; {
                    alert(&quot;Import Successful! Reloading dashboard...&quot;);
                    location.reload(); // Refresh to show new data
                };
            } catch (err) {
                alert(&quot;Error importing file: &quot; + err.message);
            }
        };
        reader.readAsText(file);
    }
&lt;/script&gt;
&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;https://yogipwd.blogspot.com/&lt;/div&gt;</description><link>https://www.yogipwd.com/2026/03/expenditure-tracker.html</link><author>noreply@blogger.com (Yogendra)</author><thr:total>0</thr:total></item></channel></rss>