Skip to content

Latest commit

 

History

History
91 lines (67 loc) · 8.21 KB

README.md

File metadata and controls

91 lines (67 loc) · 8.21 KB

Slunce Solar Calculator

Slunce is a Progressive Web App that visualises sunrise, sunset, twilight, and related solar metrics for any location on Earth. The app combines precise astronomical calculations with a lightweight UI layer and optional offline/PWA support.

High-level architecture

The codebase is intentionally small and is organised around three concerns:

  1. Presentation (index.html, style.css) – Static markup and CSS define the dashboard layout, data slots, and tooltip affordances that will be filled at runtime. 【F:index.html†L1-L211】【F:style.css†L1-L120】
  2. Behaviour (src/main.js) – Bootstraps the UI controller, handles optional ?action= URL shortcuts, and defers loading of the PWA helpers. 【F:src/main.js†L1-L45】
  3. Domain logic (src/core) – A small collection of modules that encapsulate solar calculations, time-zone heuristics, and higher level aggregates used by the UI. 【F:src/core/solarCalc.js†L1-L108】【F:src/core/solarMath.js†L1-L70】【F:src/core/solarExtras.js†L1-L200】【F:src/core/timezone.js†L1-L37】

The runtime flow is:

  1. src/main.js waits for DOMContentLoaded, initialises the UI layer, handles URL shortcuts, and registers the service worker/PWA helpers.
  2. src/ui/controller.js binds DOM listeners, loads translations, and orchestrates renders. On each render it reads the user inputs, calls into calculate from src/core/solarCalc.js, then derives secondary metrics with src/core/solarExtras.js before writing the translated results back into the DOM. 【F:src/ui/controller.js†L1-L208】【F:src/ui/controller.js†L208-L322】
  3. Optional PWA helpers (src/pwa/install.js and src/pwa/update.js) expose install prompts and update banners once the service worker (sw.js) is registered. 【F:src/pwa/install.js†L1-L83】【F:src/pwa/update.js†L1-L40】【F:sw.js†L1-L104】

Directory layout

Slunce/
├── index.html        # Markup for the dashboard and modal shells
├── style.css         # Dark themed layout + responsive tweaks
├── src/
│   ├── main.js       # Entry point (DOMContentLoaded bootstrap)
│   ├── core/
│   │   ├── solarMath.js   # Low-level astronomy formulas
│   │   ├── solarCalc.js   # Public calculate() API for sun events
│   │   ├── solarExtras.js # Secondary metrics & heuristics
│   │   └── timezone.js    # Crude tz/DST estimation by lat/lng
│   ├── ui/
│   │   └── controller.js  # DOM bindings, rendering, i18n glue
│   ├── i18n/
│   │   ├── en.js           # English strings + tooltip copy
│   │   └── cs.js           # Czech translation
│   └── pwa/
│       ├── install.js      # Install prompt / manual instructions
│       └── update.js       # Update notification workflow
├── sw.js             # Service worker (cache-first app shell)
├── manifest.json     # PWA metadata
└── icons/, favicon   # App icons referenced by the manifest

Important modules and concepts

Core solar calculations

  • solarMath.js holds pure mathematical helpers: Julian date conversion, solar declination, equation of time, and hour-angle computation. These are the foundation for every other module and are kept side-effect free for easy unit testing. 【F:src/core/solarMath.js†L1-L70】
  • solarCalc.js exposes calculate(date, lat, lng) which derives sunrise/sunset, twilight boundaries, golden/blue hour, and formats them for the UI. It gracefully handles polar day/night by returning sentinel strings such as "All day" or "No event". 【F:src/core/solarCalc.js†L1-L108】
  • solarExtras.js layers on top of calculate to compute day-to-day deltas, seasonal progress, solar geometry, photography heuristics, and physical quantities like sun distance and irradiance. Many helpers accept pre-formatted strings and convert them back to seconds when needed. 【F:src/core/solarExtras.js†L1-L200】
  • timezone.js is a pragmatic approximation that returns an offset based on coarse rectangular zones and hemisphere-specific DST heuristics. It is not exhaustive—be wary of edge cases near zone borders. 【F:src/core/timezone.js†L1-L37】

UI and internationalisation

  • src/ui/controller.js manages most of the interactivity: language detection, tooltip behaviour, input validation, geolocation, and scheduled refreshes for true solar time. Rendering is done by writing translated strings into elements addressed by IDs in index.html. The helper translateValue ensures dynamic strings (e.g., light quality labels) respect the active locale. 【F:src/ui/controller.js†L1-L322】
  • Translations live under src/i18n. English (en.js) is the source of truth; Czech (cs.js) mirrors the same keys. When adding UI copy, update both files to maintain parity. 【F:src/i18n/en.js†L1-L144】

Progressive Web App features

  • sw.js provides an app-shell cache so the experience works offline. When you change cached assets, bump CACHE_NAME to invalidate older caches. The service worker uses a cache-first strategy with network fallback and serves index.html as an offline fallback for navigation requests. 【F:sw.js†L1-L104】
  • src/pwa/install.js intercepts the browser install prompt, exposes a manual modal for unsupported platforms, and shows toast feedback on success. It relies on the globally exported getText to keep strings localised. 【F:src/pwa/install.js†L1-L83】
  • src/pwa/update.js watches for waiting service workers and surfaces an update banner that reloads the app after calling SKIP_WAITING. 【F:src/pwa/update.js†L1-L40】

Development pointers

  • Rendering loop – calculateAndRender() in the UI controller is the single render pass. If you add new metrics, compute them near the existing sections (deltas, seasonal metrics, physical quantities, photography) so they stay organised. 【F:src/ui/controller.js†L110-L208】
  • Input validation – Latitude/longitude are clamped and validated before calculations run. Reuse this logic if you add additional entry points (e.g., URL parameters). 【F:src/ui/controller.js†L118-L148】
  • Translations – All user-visible strings should be defined in the i18n files and referenced with data-i18n attributes or getText() to keep language toggling consistent. 【F:index.html†L25-L210】【F:src/ui/controller.js†L19-L75】
  • Time zones – The current estimation is intentionally lightweight. For more accuracy, consider integrating a real tz lookup service or library. Study getTimezoneFromCoordinates before making changes so you understand its fallback behaviour. 【F:src/core/timezone.js†L1-L24】
  • Testing ideas – Although there is no automated test harness yet, the deterministic core modules (solarMath.js, solarCalc.js, solarExtras.js) are prime candidates for unit tests. They have no DOM dependencies and accept plain numbers/dates.

Regression checks

To guard against timezone regressions when parsing the calendar input, run the following manual check after changes that touch date handling:

  1. Change your operating system or browser timezone to a negative UTC offset (for example, UTC−7).
  2. Load the app, pick a date such as 2024-06-21, and note the rendered events.
  3. Refresh the page or re-open it, re-select the same date, and confirm the results continue to reference that exact calendar day (no off-by-one shifts).

This ensures that local-midnight parsing remains stable for users west of the prime meridian.

Next steps for newcomers

  • Read through solarMath.js and solarCalc.js to understand the astronomical formulas and ensure future changes preserve their invariants.
  • Inspect calculateAndRender() and the DOM structure in index.html to see how data flows from inputs to outputs.
  • Experiment with the app in a browser, toggle languages, and trigger the PWA install/update flows to get a feel for the UX.
  • Consider adding automated tests or linting to guard the critical calculation modules.
  • If you plan to ship on the web, review the service worker cache list whenever you add new assets so offline support remains complete.

This overview should give you the mental map needed to dive deeper into specific features or extend the calculator. Happy hacking!