initial commit

This commit is contained in:
Ali Camarata 2023-11-11 17:23:30 +07:00
commit 82fd5feb92
8 changed files with 187 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
node_modules/
dist/
.env

7
CHANGELOG.md Normal file
View file

@ -0,0 +1,7 @@
# Changelog
All notable changes to this project will be documented in this file.
## [1.0.0] - 2023-11-11
- Initial release

7
LICENSE Normal file
View file

@ -0,0 +1,7 @@
ISC License
Copyright (c) 2023, [Your Full Name]
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

36
README.md Normal file
View file

@ -0,0 +1,36 @@
# nrel-spa
NREL SPA (Solar Position Algorithm) native implementation in JavaScript. This package allows for precise calculations of solar positions and phases based on geographical coordinates and time.
## Installation
```bash
npm install nrel-spa
```
## Usage
Basic usage examples:
```javascript
const { calcSpa } = require('nrel-spa');
const myLat = 40.7128; // Latitude for New York City
const myLng = -74.006; // Longitude for New York City
const myDate = new Date(); // Current date
const solarData = calcSpa(myDate, myLat, myLng);
console.log(solarData);
```
## API
Describe the functions and their parameters briefly.
## Contributing
Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md).
## License
This project is licensed under the ISC License - see the [LICENSE](LICENSE) file for details.

90
index.js Normal file
View file

@ -0,0 +1,90 @@
const spa = require('./dist/spa');
function fractalTime(fractionalHour) {
const hours = Math.floor(fractionalHour);
const minutes = Math.floor((fractionalHour - hours) * 60);
const seconds = Math.floor((fractionalHour * 3600) - (hours * 3600) - (minutes * 60));
const ms = Math.floor((fractionalHour * 3600000) - (hours * 3600000) - (minutes * 60000) - (seconds * 1000));
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${ms.toString().padStart(3, '0')}`;
}
function adjustForCustomAngle(baseSpaData, zenithAngle) {
let adjustedData = { ...baseSpaData };
const standardZenith = 90.83;
const angleDifference = zenithAngle - standardZenith;
const timeAdjustment = angleDifference / 360 * 24;
adjustedData.sunrise -= timeAdjustment;
adjustedData.sunset += timeAdjustment;
return adjustedData;
}
function getSpa(date, lat, lng, params = null, angles = []) {
let data = new spa.SpaData();
data.year = date.getFullYear();
data.month = date.getMonth() + 1; // JavaScript months are 0-indexed
data.day = date.getDate();
data.hour = date.getHours();
data.minute = date.getMinutes();
data.second = date.getSeconds();
data.longitude = lng;
data.latitude = lat;
// Set default values if optional parameters are not provided
data.elevation = params?.elevation ?? 10;
data.pressure = params?.pressure ?? 1013.25;
data.temperature = params?.temperature ?? 15;
data.timezone = params?.timezone ?? -5;
data.function = spa.SPA_ALL;
let result = spa.spa_calculate(data);
let output = {};
if (result === 0) {
output = {
zenith: data.zenith,
azimuth: data.azimuth,
sunrise: data.sunrise,
solarNoon: data.suntransit,
sunset: data.sunset
};
if (angles.length > 0) {
output.angles = angles.map(angle => {
let customSpaData = adjustForCustomAngle({ ...data }, angle);
return {
sunrise: customSpaData.sunrise,
sunset: customSpaData.sunset
};
});
}
} else {
console.error('SPA Calculation failed');
}
return output;
}
function calcSpa(date, lat, lng, params = null, angles = []) {
let rawData = getSpa(date, lat, lng, params, angles);
rawData.sunrise = fractalTime(rawData.sunrise);
rawData.solarNoon = fractalTime(rawData.solarNoon);
rawData.sunset = fractalTime(rawData.sunset);
if (rawData.angles) {
rawData.angles = rawData.angles.map(angleData => {
return {
sunrise: fractalTime(angleData.sunrise),
sunset: fractalTime(angleData.sunset)
};
});
}
return rawData;
}
module.exports = {
getSpa,
calcSpa,
fractalTime
};

27
package.json Normal file
View file

@ -0,0 +1,27 @@
{
"name": "nrel-spa",
"version": "1.0.0",
"description": "NREL SPA native implementation in JS",
"main": "index.js",
"scripts": {
"test": "node test.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ussunnah/nrel-spa.git"
},
"keywords": [
"spa",
"nrel",
"solar",
"calculator"
],
"author": "USF",
"license": "ISC",
"bugs": {
"url": "https://github.com/ussunnah/nrel-spa/issues"
},
"homepage": "https://github.com/ussunnah/nrel-spa#readme",
"devDependencies": {
}
}

17
test.js Normal file
View file

@ -0,0 +1,17 @@
const { getSpa, calcSpa } = require('./index');
// Constants for testing
const myLat = 40.7128; // Latitude for New York City
const myLng = -74.006; // Longitude for New York City
const nyDate = new Date(new Date().toLocaleString("en-US", { timeZone: "America/New_York" }));
const myDate = new Date(); // Date object for today with NY time zone
const myAngles = [63.435]; // Custom angles for twilight calculations
// Get results
const get = getSpa(myDate, myLat, myLng, null, myAngles);
const calc = calcSpa(myDate, myLat, myLng, null, myAngles);
// Print results
console.log("\nTest: Using NYC and current time:\n")
console.log("getSpa =", JSON.stringify(get, null, 2), "\n");
console.log("calcSpa =", JSON.stringify(calc, null, 2), "\n");