diff --git a/.travis.yml b/.travis.yml index 7a56d2a5..17ddebe4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,24 @@ +os: + - linux language: node_js node_js: - - "stable" + - "7" +sudo: required +dist: trusty +env: + - NODE_ENV=PROD +before_install: + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then export CHROME_BIN=/usr/bin/google-chrome; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then export DISPLAY=:99.0; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sh -e /etc/init.d/xvfb start; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update ; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -y libappindicator1 fonts-liberation; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb; fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo dpkg -i google-chrome*.deb; fi +install: + - npm install +before_script: + - npm run build +script: + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then jdk_switcher use oraclejdk8; fi + - npm run test diff --git a/README.md b/README.md index 94f6f7cd..acb4416a 100644 --- a/README.md +++ b/README.md @@ -1,171 +1,50 @@ - # NinjaCalc - - #### A embedded engineering calculator suite for doing calculations in a breeze. - - Author: gbmhunter ([www.mbedded.ninja](http://www.mbedded.ninja)) - Created: 2015-11-02 -- Last Modified: 2016-07-03 -- Version: v1.3.0 +- Last Modified: 2017-03-09 +- Version: v2.0.0 - Company: mbedded.ninja - Project: NinjaTerm -- Language: Java -- IDE: IntelliJ IDEA -- uC Model: n/a -- Computer Architecture: Any -- Operating System: Any -- Documentation Format: n/a +- Language: Javascript (vue.js)/HTML/CSS +- IDE: WebStorm +- Documentation Format: JSDoc - License: GPLv3 - # Motivation +The goal of this is to provide a easy-to-use web application to help you with all those small, frequent calculations you do while doing embedded engineering (or other forms of engineering). Whether it be a low-pass LC filter, a resistor divider, trying to find PCB track current, or even just Ohm's law (o.k., I hope you don't forget that one, but it is included none-the-less), this app makes them easy to find, use, and have confidence in the answers. -The goal of this is to provide a easy-to-use desktop application to help you with all those small, frequent calculations you do while doing embedded engineering (or other forms of engineering). Whether it be a low-pass LC filter, a resistor divider, trying to find PCB track current, or even just Ohm's law (o.k., I hope you don't forget that one, but it is included none-the-less), this app makes them easy to find, use, and have confidence in the answers. +# To Use +Go to http://ninja-calc.mbedded.ninja/ # Features - See the [project home page](http://mbedded-ninja.github.io/NinjaCalc/) for a list of features. - -# Installation - - -1. Download the latest installer-based release from [http://mbedded-ninja.github.io/NinjaCalc/](http://mbedded-ninja.github.io/NinjaCalc/). -2. Run the installer and play (or work, right?)! -3. NinjaCalc should automatically inform you if there is a new version available on start-up of the application. - -Note: Installing a newer version of NinjaCalc should automatically overwrite the old one. - - # Developing - 1. Download/clone this repository into a folder on your computer. -2. Make sure you have a 32-bit version of the JDK installed (must be at least JDK 8). -3. Open the project in IntelliJ (`.idea/workspace.xml` file included in repo). -4. In IntelliJ, open the project settings, and point the projects JDK to installed version on your computer. -5. Develop! - -[Scene Builder](http://gluonhq.com/labs/scene-builder/) can be great tool to install alongside IntelliJ for faster development of the JavaFX UI. - - -# Making Your Own Calculators - -There are many pre-built calculator view objects to make development faster and keep a consistent look and feel across the application. These are located in `src/Core/View`. This includes: - -1. A Dimension object - - -# Creating A Calculator Diagram - -Creating a static diagram image and laying the calculator variable UI elements overtop of this is the easiest method to create a diagram when dynamic visual changes to the diagram are not required. - -All calculators that use static images for their background diagrams have a Visio file called `diagram.vsd` in their respective folder. Microsoft Visio is used to create the diagram, which is then exported as an image and used inside the NinjaCalc application. - - -# Release Process - -The team at [ej-technologies](https://www.ej-technologies.com/) have graciously donated me an open-source licensed version of ![install4j](https://www.ej-technologies.com/images/product_banners/install4j_small.png), [the multi-platform installer builder for Java applications](http://www.ej-technologies.com/products/install4j/overview.html). - -Myself (gbmhunter) currently holds the license for this software, and so I am the only one that can currently create installable packages for NinjaCalc releases. - -The install4j script is located at `/NinjaCalc.install4j`. - -1. After code changes are complete, make sure the NinjaCalc.jar artifact has been built from within IntelliJ (`Build->Build Artifacts->NinjaCalc:jar->Build`). -2. Open the `/NinjaCalc.install4j` file in "install4j Multi-Platform Edition". -3. Update the "Version" field as appropriate, then click "Save Project". -4. Click the "Build Project" button. -5. Wait until build completes. install4j should have created installer files for each supported platform (currently Windows and Mac OS), as well as an updates.xml file, in the `install` directory. -6. Overwrite the old `updates.xml` file in the repos root directory with the one that install4j created in the `install` directory. -7. Upload the installable packages to GitHub as a new release (if appropriate). -8. Commit and push the repository changes to the master branch (updates.xml is the most important file to be updated). The "Git Flow" plugin for SourceTree can make this step easy. -9. Update the download button links on the homepage in the `gh-pages` branch of the repo to point to the new release files. - - -# Debugging A Deployed App (Locally) +1. Run `npm install` to install dependencies (make sure node/npm is installed on your system). +1. Open the project in WebStorm (`.idea/workspace.xml` file included in repo), or your favourite text/code editor. +1. Develop! -You can get the `System.out` and `System.err` streams by running the `NinjaCalc.jar` file from the commandline. For example, in Windows you would type at the command-line: +# Releasing - -`C:\Program Files (x86)\NinjaCalc\java -jar NinjaCalc.jar` - -# File Structure - - -Sorted by alphabetical order. - -### (root level) - -Contains the install4j script for generating single-file installable packages for the various operating systems. - - -### install/ - -The install4j script in the repo's root directory will instruct install4j to place deployment-ready NinjaCalc installers for the various operating systems here. - - -### out/ - -IntelliJ IDEA will place output Java files when debugging/building in this directory. - - -### src/ - -Contains the source code. This is split into the following sub-directories: - -calculators/ - Contains all of the data to create each calculator type. - -Core/ - Contains all the "core", non-calculator specific classes that make up the backend calculator engine and front-end visual elements. - -Img/ - Contains images which are incorporated into the app. - -MainWindow/ - Contains the Java code and .fxml file describing the main window of NinjaCalc. - -test/ - Unit tests for each of the calculators, core modules and utility modules. The unit tests include the testing of the UI (more on this below). - -Utility/ - Contains helper Java classes which are not considered "core", but still used by multiple calculators. This includes things such as a library to help you find the closest standard E-series resistance (preferred value), and a library to convert from doubles to strings with metric prefixes and back again. - - -# Unit Tests - -Unit tests are under the `test/` directory. This directory mimics the same directory structure of `src/`. - -Tests are easily run from within IntelliJ. To run all tests, right click on the `test` folder from within IntelliJ and click *Run 'All Tests'*. - -Tests involving JavaFX can be easily written by making sure the test class in question extends `ApplicationTest`. `ApplicationTest` is a class from the [TestFX library](https://github.com/TestFX/TestFX) which is used here to test the JavaFX UI for each calculator. The `ApplicationTest` class makes sure that JavaFX is initialised correctly before your tests are run. You have to provide a `start(Stage stage)` method for each test class. Here is an example: - -````java -import javafx.stage.Stage; -import javafx.scene.control.TextField; -import org.junit.Test; -import org.testfx.framework.junit.ApplicationTest; - -public class ExampleJavaFxTests extends ApplicationTest { - - @Override - public void start(Stage stage) { - } - - @Test - public void basicFirstTest() { - // You can create JavaFX object here and they will work correctly - // (no initialisation exceptions will be thrown) - TextField textField = new TextField(); - } -} -```` +1. Make sure you are on the `develop` branch and all changes from `feature/xxx` branches have been merged into it. +1. Update `changelog.md` with a list of changes since the last release, under a heading which is the new version number (e.g. `v1.2.0`). +1. Commit the changes made above to the `develop` branch. +1. Merge the `develop` branch into the `master` branch. +1. Tag the commit on the master branch with the version number (e.g. `v1.2.0`). +1. Push all branches to the remote GitHub repo. Heroku will automatically build and deploy the new version committed onto the `master` branch. # Changelog See [changelog.md](../blob/master/changelog.md). - # Contributors -See the [project home page](http://mbedded-ninja.github.io/NinjaCalc/) for a list of contributors. \ No newline at end of file +See the [project home page](http://mbedded-ninja.github.io/NinjaCalc/) for a list of contributors. diff --git a/changelog.md b/changelog.md index 15567053..00b565cb 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,12 @@ +v2.1.0 +------ + +- Added data so that NinjaCalc website appears correctly when linked to on social media, closes #136. +- Added ability to close a calculator tab, closes #139. +- Added support for function-based units for numerical calculator variables, closes #140. +- Removed value property from the Unit class, closes #141. +- Added "search" functionality to the calculator selection overlay, closes #142. + v2.0.0 ------ diff --git a/index.html b/index.html index f94cc6dc..7b47c8ba 100644 --- a/index.html +++ b/index.html @@ -2,11 +2,16 @@ - vue-webpack + NinjaCalc - + + + + +
diff --git a/package.json b/package.json index 21bb1aba..bc34f9ee 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", "unit-cont": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js", "e2e": "node test/e2e/runner.js", - "test": "npm run unit", + "test": "npm run unit && npm run e2e", "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs", "postinstall": "npm run build", "start": "node server.js" @@ -69,6 +69,7 @@ "opn": "^4.0.2", "optimize-css-assets-webpack-plugin": "^1.3.0", "ora": "^1.1.0", + "phantomjs-polyfill-find": "github:ptim/phantomjs-polyfill-find", "phantomjs-prebuilt": "^2.1.14", "rimraf": "^2.6.0", "selenium-server": "^3.0.1", diff --git a/src/App.vue b/src/App.vue index b7da2fa5..fa6cdc91 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,7 +28,9 @@ - + + @@ -45,6 +47,8 @@ @@ -198,6 +213,13 @@ padding-right: 10px; } + /* This hides the "+" button which is automatically added + to the far-right of the tab header when the "editable" + property is supplied to the tab component */ + span.el-tabs__new-tab { + display: none; + } + div.el-tabs__content { height: 100%; } diff --git a/src/components/CalcPreview/CalcPreview.vue b/src/components/CalcPreview/CalcPreview.vue index 37945003..c772b2c6 100644 --- a/src/components/CalcPreview/CalcPreview.vue +++ b/src/components/CalcPreview/CalcPreview.vue @@ -3,10 +3,16 @@
+
+ +
+
{{ title }}
+
+
{{ description }}
+
-
{{ title }}
- -
{{ description }}
Open
@@ -68,15 +74,18 @@ /* The slow way */ #calc-preview-container { + /* Width and height sets the dimensions for each + calculator preview.*/ width: 200px; height: 300px; margin: 10px; padding: 5px; - display: flex; - flex-direction: column; - justify-content: space-around; + position: relative; + /*display: flex;*/ + /*flex-direction: column;*/ + /*justify-content: space-around;*/ border-radius: 5px; border-color: #cdcdcd; @@ -85,6 +94,11 @@ box-shadow: 0 2px 4px rgba(0,0,0,0.20); transition: box-shadow 0.3s ease-in-out; + + /* Giving the calculator preview objects a background color + makes the move transition applied to them look better (when one slides over another, + you can't see them both) */ + background-color: white; } /* Transition to a bigger shadow on hover */ @@ -92,7 +106,7 @@ box-shadow: 0 5px 15px rgba(0,0,0,0.3); } - #image-wrapper { + div#image-wrapper { /* This makes the image wrapper always the same height, even though the actual height of the image may differ slightly */ height: 120px; @@ -110,19 +124,12 @@ height: auto; } - #title { - font-size: 20px; - font-weight: 500; - } + div#open-button { - #description { - font-size: 12px; - } - - #open-button { - margin-right: 10px; - display: flex; - justify-content: flex-end; + /* Position button at bottom right */ + position: absolute; + bottom: 10px; + right: 10px; } diff --git a/src/components/CalculatorSelectionOverlay/CalculatorSelectionOverlay.vue b/src/components/CalculatorSelectionOverlay/CalculatorSelectionOverlay.vue index 733ec90d..f0d9d554 100644 --- a/src/components/CalculatorSelectionOverlay/CalculatorSelectionOverlay.vue +++ b/src/components/CalculatorSelectionOverlay/CalculatorSelectionOverlay.vue @@ -1,25 +1,28 @@ @@ -17,6 +17,7 @@ // 'use strict' import { CalcVarNumeral } from 'src/misc/CalculatorEngineV2/CalcVarNumeral' + import { UnitMulti } from 'src/misc/CalculatorEngineV2/UnitMulti' import PresetValidators from 'src/misc/CalculatorEngineV2/PresetValidators' import StandardResistanceFinder from 'src/misc/StandardResistanceFinder/StandardResistanceFinder' @@ -54,9 +55,9 @@ }, rawVal: '', units: [ - {text: 'V', value: 1} + new UnitMulti({name: 'Ω', multi: 1e0}) ], - selUnit: 1, + defaultUnitName: 'Ω', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -86,9 +87,9 @@ }, rawVal: '', units: [ - {text: 'V', value: 1} + new UnitMulti({name: '%', multi: 1e0}) ], - selUnit: 1, + defaultUnitName: '%', roundTo: 2, validators: [ PresetValidators.IS_NUMBER, @@ -113,9 +114,9 @@ }, rawVal: '', units: [ - {text: 'V', value: 1} + new UnitMulti({name: 'Ω', multi: 1e0}) ], - selUnit: 1, + defaultUnitName: 'Ω', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -144,9 +145,9 @@ }, rawVal: '', units: [ - {text: 'V', value: 1} + new UnitMulti({name: '%', multi: 1e0}) ], - selUnit: 1, + defaultUnitName: '%', roundTo: 2, validators: [ PresetValidators.IS_NUMBER, @@ -171,9 +172,9 @@ }, rawVal: '', units: [ - {text: 'V', value: 1} + new UnitMulti({name: 'Ω', multi: 1e0}) ], - selUnit: 1, + defaultUnitName: 'Ω', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -202,9 +203,9 @@ }, rawVal: '', units: [ - {text: 'V', value: 1} + new UnitMulti({name: '%', multi: 1e0}) ], - selUnit: 1, + defaultUnitName: '%', roundTo: 2, validators: [ PresetValidators.IS_NUMBER, @@ -217,9 +218,7 @@ return { } }, - mounted () { - console.log('ESeriesRow mounted.') - } + mounted () {} } diff --git a/src/components/Calculators/Electronics/Basic/StandardResistance/MainView.vue b/src/components/Calculators/Electronics/Basic/StandardResistance/MainView.vue index 69e41625..b4ade381 100644 --- a/src/components/Calculators/Electronics/Basic/StandardResistance/MainView.vue +++ b/src/components/Calculators/Electronics/Basic/StandardResistance/MainView.vue @@ -63,7 +63,8 @@ // 'use strict' import Calc from 'src/misc/CalculatorEngineV2/Calc' - import { CalcVarNumeral } from 'src/misc/CalculatorEngineV2/CalcVarNumeral' + import {CalcVarNumeral} from 'src/misc/CalculatorEngineV2/CalcVarNumeral' + import {UnitMulti} from 'src/misc/CalculatorEngineV2/UnitMulti' import PresetValidators from 'src/misc/CalculatorEngineV2/PresetValidators' import { CustomValidator } from 'src/misc/CalculatorEngineV2/CustomValidator' @@ -96,10 +97,13 @@ }, rawVal: '', units: [ - {text: 'mV', value: 1e-3}, - {text: 'V', value: 1} + new UnitMulti({name: 'mΩ', multi: 1e-3}), + new UnitMulti({name: 'Ω', multi: 1e0}), + new UnitMulti({name: 'kΩ', multi: 1e3}), + new UnitMulti({name: 'MΩ', multi: 1e6}), + new UnitMulti({name: 'GΩ', multi: 1e9}) ], - selUnit: 1, + defaultUnitName: 'Ω', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, diff --git a/src/components/Calculators/Electronics/Filters/LowPassRC/Calc.js b/src/components/Calculators/Electronics/Filters/LowPassRC/Calc.js index 75a481d3..d72ee63e 100644 --- a/src/components/Calculators/Electronics/Filters/LowPassRC/Calc.js +++ b/src/components/Calculators/Electronics/Filters/LowPassRC/Calc.js @@ -2,7 +2,7 @@ import MainView from './MainView' export default { displayName: 'Low Pass RC', - description: 'The low-pass RC filter is probably the simplist and most used electronic filter. Great for input signal filtering and adding to the output of a PWM signal to make a cheap DAC.', + description: 'The low-pass RC filter is probably the simplist and most used electronic filter. Great for input signal filtering.', imagePath: require('./grid-icon.png'), category: [ 'Electronics', 'Filters' ], tags: [ 'rc', 'filters', 'filtering', 'low-pass', 'adc', 'signal', 'conditioning', 'processing' ], diff --git a/src/components/Calculators/Electronics/Filters/LowPassRC/MainView.vue b/src/components/Calculators/Electronics/Filters/LowPassRC/MainView.vue index 703743d4..69fda182 100644 --- a/src/components/Calculators/Electronics/Filters/LowPassRC/MainView.vue +++ b/src/components/Calculators/Electronics/Filters/LowPassRC/MainView.vue @@ -58,6 +58,7 @@ import Calc from 'src/misc/CalculatorEngineV2/Calc' import {CalcVarNumeral} from 'src/misc/CalculatorEngineV2/CalcVarNumeral' + import {UnitMulti} from 'src/misc/CalculatorEngineV2/UnitMulti' import PresetValidators from 'src/misc/CalculatorEngineV2/PresetValidators' // ============================================ // @@ -93,12 +94,12 @@ }, rawVal: '', units: [ - {text: 'mΩ', value: 1e-3}, - {text: 'Ω', value: 1}, - {text: 'kΩ', value: 1e3}, - {text: 'MΩ', value: 1e6} + new UnitMulti({name: 'mΩ', multi: 1e-3}), + new UnitMulti({name: 'Ω', multi: 1e0}), + new UnitMulti({name: 'kΩ', multi: 1e3}), + new UnitMulti({name: 'MΩ', multi: 1e6}) ], - selUnit: 1, + defaultUnitName: 'kΩ', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -128,13 +129,13 @@ }, rawVal: '', units: [ - {text: 'pF', value: 1e-12}, - {text: 'nF', value: 1e-9}, - {text: 'uF', value: 1e-6}, - {text: 'mF', value: 1e-3}, - {text: 'F', value: 1} + new UnitMulti({name: 'pF', multi: 1e-12}), + new UnitMulti({name: 'nF', multi: 1e-9}), + new UnitMulti({name: 'uF', multi: 1e-6}), + new UnitMulti({name: 'mF', multi: 1e-3}), + new UnitMulti({name: 'F', multi: 1e0}) ], - selUnit: 1, + defaultUnitName: 'uF', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -164,12 +165,12 @@ }, rawVal: '', units: [ - {text: 'Hz', value: 1e0}, - {text: 'kHz', value: 1e3}, - {text: 'MHz', value: 1e6}, - {text: 'GHz', value: 1e9} + new UnitMulti({name: 'Hz', multi: 1e0}), + new UnitMulti({name: 'kHz', multi: 1e0}), + new UnitMulti({name: 'MHz', multi: 1e0}), + new UnitMulti({name: 'GHz', multi: 1e0}) ], - selUnit: 1, + defaultUnitName: 'kHz', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, diff --git a/src/components/Calculators/Electronics/Pcb/TrackCurrentIpc2152/MainView.vue b/src/components/Calculators/Electronics/Pcb/TrackCurrentIpc2152/MainView.vue index f589ade6..951471ea 100644 --- a/src/components/Calculators/Electronics/Pcb/TrackCurrentIpc2152/MainView.vue +++ b/src/components/Calculators/Electronics/Pcb/TrackCurrentIpc2152/MainView.vue @@ -181,22 +181,16 @@ import Calc from 'src/misc/CalculatorEngineV2/Calc' import {CalcVarNumeral} from 'src/misc/CalculatorEngineV2/CalcVarNumeral' import {CalcVarComboBox} from 'src/misc/CalculatorEngineV2/CalcVarComboBox' + import {UnitMulti} from 'src/misc/CalculatorEngineV2/UnitMulti' + import {UnitFunc} from 'src/misc/CalculatorEngineV2/UnitFunc' import PresetValidators from 'src/misc/CalculatorEngineV2/PresetValidators' import {CustomValidator} from 'src/misc/CalculatorEngineV2/CustomValidator' + import {unitConversionConstants} from 'src/misc/UnitConversionConstants/UnitConversionConstants' // ============================================================================================= // // ============================================ CONSTANTS ====================================== // // ============================================================================================= // const NUM_MILS_PER_MM = 1000 / 25.4 - // const UNIT_CONVERSION_COPPER_THICKNESS_M_PER_OZ = 0.0000350012 - const UNIT_CONVERSION_M_PER_MIL = 25.4 / 1e6 - const UNIT_CONVERSION_M2_PER_MIL2 = UNIT_CONVERSION_M_PER_MIL * UNIT_CONVERSION_M_PER_MIL - const UNIT_CONVERSION_THERMAL_CONDUCTIVITY_WATT_nMETER_nKELVIN_PER_BTU_nHOUR_nFT_nDEGF = 1.73 // eslint-disable-line camelcase - const COPPER_THICKNESS_M_PER_OZ = 0.0000350012 - const METERS_PER_INCH = 25.4 / 1000 - const METERS_PER_MILS = METERS_PER_INCH / 1000.0 - - // const UNIT_CONVERSION_THERMAL_CONDUCTIVITY_WATT_nMETER_nKELVIN_PER_BTU_nHOUR_nFT_nDEGF = 1.73 // UNIVERSAL CHART CONSTANTS @@ -288,11 +282,11 @@ }, rawVal: '', units: [ - {text: 'uA', value: 1e-6}, - {text: 'mA', value: 1e-3}, - {text: 'A', value: 1} + new UnitMulti({name: 'uA', multi: 1e-6}), + new UnitMulti({name: 'mA', multi: 1e-3}), + new UnitMulti({name: 'A', multi: 1e0}) ], - selUnit: 1, + defaultUnitName: 'A', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -333,9 +327,18 @@ }, rawVal: '', units: [ - {text: '°C', value: 1e0} + new UnitMulti({ name: '°C', multi: 1e0 }), + new UnitFunc({ + name: 'F', + toUnit: function (baseValue) { + return baseValue * 1.8 + 32 + }, + fromUnit: function (unitValue) { + return (unitValue - 32) / 1.8 + } + }) ], - selUnit: 1, + defaultUnitName: '°C', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -391,11 +394,11 @@ }, rawVal: '', units: [ - {text: 'um²', value: 1e-12}, - {text: 'mils²', value: UNIT_CONVERSION_M2_PER_MIL2}, - {text: 'mm²', value: 1e-6} + new UnitMulti({ name: 'um²', multi: 1e-12 }), + new UnitMulti({ name: 'mils²', multi: unitConversionConstants.M2_PER_MIL2 }), + new UnitMulti({ name: 'mm²', multi: 1e-6 }) ], - selUnit: 1e-12, + defaultUnitName: 'um²', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -416,12 +419,12 @@ }, rawVal: '', units: [ - {text: 'um', value: 1e-6}, - {text: 'mm', value: 1e-3}, - {text: 'oz', value: COPPER_THICKNESS_M_PER_OZ}, - {text: 'mils', value: METERS_PER_MILS} + new UnitMulti({name: 'um', multi: 1e-6}), + new UnitMulti({name: 'mm', multi: 1e-3}), + new UnitMulti({name: 'oz', multi: unitConversionConstants.COPPER_THICKNESS_M_PER_OZ}), + new UnitMulti({name: 'mils', multi: unitConversionConstants.METERS_PER_MILS}) ], - selUnit: 1e-6, + defaultUnitName: 'um', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -464,7 +467,7 @@ const trackThicknessM = calc.getVar('trackThickness').getRawVal() // Convert to "oz" units, as this is what is used in IPC-2152 graphs - const trackThicknessOz = trackThicknessM * (1 / COPPER_THICKNESS_M_PER_OZ) + const trackThicknessOz = trackThicknessM * (1 / unitConversionConstants.COPPER_THICKNESS_M_PER_OZ) // Lets calculate the two co-efficients for the fixed-temp trend line // double[] trackThicknessTrendLineCoefA = new double[TRACK_THICKNESS_TREND_LINE_COEF_COEF_A.length]; @@ -492,9 +495,9 @@ }, rawVal: '', units: [ - {text: 'no unit', value: 1e0} + new UnitMulti({name: 'no unit', multi: 1e0}) ], - selUnit: 1e0, + defaultUnitName: 'no unit', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -515,11 +518,11 @@ }, rawVal: '', units: [ - {text: 'um', value: 1e-6}, - {text: 'mm', value: 1e-3}, - {text: 'mils', value: METERS_PER_MILS} + new UnitMulti({name: 'um', multi: 1e-6}), + new UnitMulti({name: 'mm', multi: 1e-3}), + new UnitMulti({name: 'mils', multi: unitConversionConstants.METERS_PER_MILS}) ], - selUnit: 1e-3, + defaultUnitName: 'mm', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -561,7 +564,7 @@ const boardThicknessM = calc.getVar('boardThickness').getRawVal() // Convert to "mils" units, as this is what is used in IPC-2152 graphs - const boardThicknessMils = boardThicknessM * (1 / UNIT_CONVERSION_M_PER_MIL) + const boardThicknessMils = boardThicknessM * (1 / unitConversionConstants.METERS_PER_MILS) const boardThicknessModifierMulti = BOARD_THICKNESS_TREND_LINE_COEF_A * Math.pow(boardThicknessMils, BOARD_THICKNESS_TREND_LINE_COEF_B) @@ -570,9 +573,9 @@ }, rawVal: '', units: [ - {text: 'no unit', value: 1e0} + new UnitMulti({name: 'no unit', multi: 1e0}) ], - selUnit: 1e0, + defaultUnitName: 'no unit', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -607,11 +610,11 @@ }, rawVal: '', units: [ - {text: 'um', value: 1e-6}, - {text: 'mm', value: 1e-3}, - {text: 'mils', value: METERS_PER_MILS} + new UnitMulti({name: 'um', multi: 1e-6}), + new UnitMulti({name: 'mm', multi: 1e-3}), + new UnitMulti({name: 'mils', multi: unitConversionConstants.METERS_PER_MILS}) ], - selUnit: 1e-3, + defaultUnitName: 'mm', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -673,7 +676,7 @@ // Plane must be present at this point // Convert to "mils" units, as this is what is used in IPC-2152 graphs - const planeProximityMils = planeProximityM * (1 / UNIT_CONVERSION_M_PER_MIL) + const planeProximityMils = planeProximityM * (1 / unitConversionConstants.METERS_PER_MILS) const planeProximityModifierMulti = PLANE_PROXIMITY_TREND_LINE_COEF_M * planeProximityMils + PLANE_PROXIMITY_TREND_LINE_COEF_C @@ -682,9 +685,9 @@ }, rawVal: '', units: [ - {text: 'no unit', value: 1e0} + new UnitMulti({name: 'no unit', multi: 1e0}) ], - selUnit: 1e0, + defaultUnitName: 'no unit', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -705,13 +708,10 @@ }, rawVal: '0.20', units: [ - {text: 'W/(m*K)', value: 1e0}, - { - text: 'BTU/(hour*ft*F)', - value: UNIT_CONVERSION_THERMAL_CONDUCTIVITY_WATT_nMETER_nKELVIN_PER_BTU_nHOUR_nFT_nDEGF - } + new UnitMulti({name: 'W/(m*K)', multi: 1e0}), + new UnitMulti({name: 'BTU/(hour*ft*F)', multi: unitConversionConstants.THERMAL_CONDUCTIVITY_WATT_nMETER_nKELVIN_PER_BTU_nHOUR_nFT_nDEGF}) ], - selUnit: 1e0, + defaultUnitName: 'W/(m*K)', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -754,7 +754,7 @@ // Convert to BTU/(ft*hour*F), as this is what the IPC-2152 graph used const thermalConductivityBtunFtnHournDegF = thermalConductivityWattnMeternDegC * - (1 / UNIT_CONVERSION_THERMAL_CONDUCTIVITY_WATT_nMETER_nKELVIN_PER_BTU_nHOUR_nFT_nDEGF) // eslint-disable-line camelcase + (1 / unitConversionConstants.THERMAL_CONDUCTIVITY_WATT_nMETER_nKELVIN_PER_BTU_nHOUR_nFT_nDEGF) // eslint-disable-line camelcase const thermalConductivityModifierMulti = THERMAL_CONDUCTIVITY_TREND_LINE_COEF_M * thermalConductivityBtunFtnHournDegF + THERMAL_CONDUCTIVITY_TREND_LINE_COEF_C @@ -763,9 +763,9 @@ }, rawVal: '', units: [ - {text: 'no unit', value: 1e0} + new UnitMulti({name: 'no unit', multi: 1e0}) ], - selUnit: 1e0, + defaultUnitName: 'no unit', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -801,11 +801,11 @@ }, rawVal: '', units: [ - {text: 'um²', value: 1e-12}, - {text: 'mils²', value: UNIT_CONVERSION_M2_PER_MIL2}, - {text: 'mm²', value: 1e-6} + new UnitMulti({ name: 'um²', multi: 1e-12 }), + new UnitMulti({ name: 'mils²', multi: unitConversionConstants.M2_PER_MIL2 }), + new UnitMulti({ name: 'mm²', multi: 1e-6 }) ], - selUnit: 1e-12, + defaultUnitName: 'um²', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -833,11 +833,11 @@ }, rawVal: '', units: [ - {text: 'um', value: 1e-6}, - {text: 'mm', value: 1e-3}, - {text: 'mils', value: METERS_PER_MILS} + new UnitMulti({name: 'um', multi: 1e-6}), + new UnitMulti({name: 'mm', multi: 1e-3}), + new UnitMulti({name: 'mils', multi: unitConversionConstants.METERS_PER_MILS}) ], - selUnit: 1e-3, + defaultUnitName: 'mm', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, diff --git a/src/components/Calculators/Electronics/Pcb/TrackCurrentIpc2221A/MainView.vue b/src/components/Calculators/Electronics/Pcb/TrackCurrentIpc2221A/MainView.vue index 75da97ba..3b80a880 100644 --- a/src/components/Calculators/Electronics/Pcb/TrackCurrentIpc2221A/MainView.vue +++ b/src/components/Calculators/Electronics/Pcb/TrackCurrentIpc2221A/MainView.vue @@ -106,15 +106,17 @@ import Calc from 'src/misc/CalculatorEngineV2/Calc' import {CalcVarNumeral} from 'src/misc/CalculatorEngineV2/CalcVarNumeral' import {CalcVarComboBox} from 'src/misc/CalculatorEngineV2/CalcVarComboBox' + import {UnitMulti} from 'src/misc/CalculatorEngineV2/UnitMulti' + import {UnitFunc} from 'src/misc/CalculatorEngineV2/UnitFunc' import PresetValidators from 'src/misc/CalculatorEngineV2/PresetValidators' import {CustomValidator} from 'src/misc/CalculatorEngineV2/CustomValidator' + import {unitConversionConstants} from 'src/misc/UnitConversionConstants/UnitConversionConstants' // ============================================================================================= // // ============================================ CONSTANTS ====================================== // // ============================================================================================= // - const COPPER_THICKNESS_M_PER_OZ = 0.0000350012 - const METERS_PER_INCH = 25.4 / 1000 - const METERS_PER_MILS = METERS_PER_INCH / 1000.0 +// const METERS_PER_INCH = 25.4 / 1000 +// const METERS_PER_MILS = METERS_PER_INCH / 1000.0 // ============================================ // // =================== vue Object ============= // @@ -137,11 +139,11 @@ }, rawVal: '', units: [ - {text: 'uA', value: 1e-6}, - {text: 'mA', value: 1e-3}, - {text: 'A', value: 1} + new UnitMulti({name: 'uA', multi: 1e-6}), + new UnitMulti({name: 'mA', multi: 1e-3}), + new UnitMulti({name: 'A', multi: 1e0}) ], - selUnit: 1e0, + defaultUnitName: 'A', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -171,9 +173,18 @@ }, rawVal: '', units: [ - {text: '°C', value: 1e0} + new UnitMulti({ name: '°C', multi: 1e0 }), + new UnitFunc({ + name: 'F', + toUnit: function (baseValue) { + return baseValue * 1.8 + 32 + }, + fromUnit: function (unitValue) { + return (unitValue - 32) / 1.8 + } + }) ], - selUnit: 1e0, + defaultUnitName: '°C', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -212,12 +223,12 @@ }, rawVal: '', units: [ - {text: 'um', value: 1e-6}, - {text: 'mm', value: 1e-3}, - {text: 'oz', value: COPPER_THICKNESS_M_PER_OZ}, - {text: 'mils', value: METERS_PER_MILS} + new UnitMulti({name: 'um', multi: 1e-6}), + new UnitMulti({name: 'mm', multi: 1e-3}), + new UnitMulti({name: 'oz', multi: unitConversionConstants.COPPER_THICKNESS_M_PER_OZ}), + new UnitMulti({name: 'mils', multi: unitConversionConstants.METERS_PER_MILS}) ], - selUnit: 1e-6, + defaultUnitName: 'um', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -285,11 +296,11 @@ }, rawVal: '', units: [ - {text: 'um', value: 1e-6}, - {text: 'mm', value: 1e-3}, - {text: 'mils', value: METERS_PER_MILS} + new UnitMulti({name: 'um', multi: 1e-6}), + new UnitMulti({name: 'mm', multi: 1e-3}), + new UnitMulti({name: 'mils', multi: unitConversionConstants.METERS_PER_MILS}) ], - selUnit: 1e-3, + defaultUnitName: 'mm', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, diff --git a/src/components/Calculators/Electronics/Pcb/ViaCurrentIpc2221A/MainView.vue b/src/components/Calculators/Electronics/Pcb/ViaCurrentIpc2221A/MainView.vue index f310d7f3..0ba8cc94 100644 --- a/src/components/Calculators/Electronics/Pcb/ViaCurrentIpc2221A/MainView.vue +++ b/src/components/Calculators/Electronics/Pcb/ViaCurrentIpc2221A/MainView.vue @@ -118,8 +118,10 @@ import Calc from 'src/misc/CalculatorEngineV2/Calc' import {CalcVarNumeral} from 'src/misc/CalculatorEngineV2/CalcVarNumeral' + import {UnitMulti} from 'src/misc/CalculatorEngineV2/UnitMulti' + import {UnitFunc} from 'src/misc/CalculatorEngineV2/UnitFunc' import PresetValidators from 'src/misc/CalculatorEngineV2/PresetValidators' - import {UnitConversionConstants} from 'src/misc/UnitConversionConstants/UnitConversionConstants' + import {unitConversionConstants} from 'src/misc/UnitConversionConstants/UnitConversionConstants' /* eslint-disable camelcase */ @@ -148,10 +150,11 @@ }, rawVal: '', units: [ - {text: 'um', value: 1e-6}, - {text: 'mm', value: 1e-3} + new UnitMulti({name: 'um', multi: 1e-6}), + new UnitMulti({name: 'mm', multi: 1e-3}), + new UnitMulti({name: 'mils', multi: unitConversionConstants.METERS_PER_MILS}) ], - selUnit: 1e-3, + defaultUnitName: 'mm', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -172,11 +175,12 @@ }, rawVal: '', units: [ - {text: 'um', value: 1e-6}, - {text: 'oz', value: UnitConversionConstants.COPPER_THICKNESS_M_PER_OZ}, - {text: 'mils', value: UnitConversionConstants.METERS_PER_MILS} + new UnitMulti({name: 'um', multi: 1e-6}), + new UnitMulti({name: 'mm', multi: 1e-3}), + new UnitMulti({name: 'oz', multi: unitConversionConstants.COPPER_THICKNESS_M_PER_OZ}), + new UnitMulti({name: 'mils', multi: unitConversionConstants.METERS_PER_MILS}) ], - selUnit: 1e-6, + defaultUnitName: 'um', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -197,11 +201,11 @@ }, rawVal: '', units: [ - {text: 'um', value: 1e-6}, - {text: 'mm', value: 1e-3}, - {text: 'mils', value: UnitConversionConstants.METERS_PER_MILS} + new UnitMulti({name: 'um', multi: 1e-6}), + new UnitMulti({name: 'mm', multi: 1e-3}), + new UnitMulti({name: 'mils', multi: unitConversionConstants.METERS_PER_MILS}) ], - selUnit: 1e-3, + defaultUnitName: 'mm', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -223,9 +227,18 @@ }, rawVal: '20.0', units: [ - {text: '°C', value: 1e0} + new UnitMulti({ name: '°C', multi: 1e0 }), + new UnitFunc({ + name: 'F', + toUnit: function (baseValue) { + return baseValue * 1.8 + 32 + }, + fromUnit: function (unitValue) { + return (unitValue - 32) / 1.8 + } + }) ], - selUnit: 1e0, + defaultUnitName: '°C', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -246,9 +259,9 @@ }, rawVal: '19e-9', units: [ - {text: 'Ω⋅m', value: 1e0} + new UnitMulti({name: 'Ω⋅m', multi: 1e0}) ], - selUnit: 1e0, + defaultUnitName: 'Ω⋅m', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -269,9 +282,9 @@ }, rawVal: '401.8', units: [ - {text: 'W/K⋅m', value: 1e0} + new UnitMulti({name: 'W/K⋅m', multi: 1e0}) ], - selUnit: 1e0, + defaultUnitName: 'W/K⋅m', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -297,9 +310,11 @@ }, rawVal: '', units: [ - {text: 'm2', value: 1e0} + new UnitMulti({ name: 'um²', multi: 1e-12 }), + new UnitMulti({ name: 'mils²', multi: unitConversionConstants.M2_PER_MIL2 }), + new UnitMulti({ name: 'mm²', multi: 1e-6 }) ], - selUnit: 1e0, + defaultUnitName: 'um²', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -326,9 +341,9 @@ }, rawVal: '', units: [ - {text: 'mΩ', value: 1e-3} + new UnitMulti({ name: 'mΩ', multi: 1e-3 }) ], - selUnit: 1e-3, + defaultUnitName: 'mΩ', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -355,9 +370,9 @@ }, rawVal: '', units: [ - {text: '°C/W', value: 1e0} + new UnitMulti({ name: '°C/W', multi: 1e0 }) ], - selUnit: 1e0, + defaultUnitName: '°C/W', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -387,9 +402,11 @@ }, rawVal: '', units: [ - {text: 'A', value: 1e0} + new UnitMulti({name: 'uA', multi: 1e-6}), + new UnitMulti({name: 'mA', multi: 1e-3}), + new UnitMulti({name: 'A', multi: 1}) ], - selUnit: 1e0, + defaultUnitName: 'A', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, diff --git a/src/components/Calculators/Electronics/Sensors/DewPointMagnus/MainView.vue b/src/components/Calculators/Electronics/Sensors/DewPointMagnus/MainView.vue index 45d5794d..bae58b83 100644 --- a/src/components/Calculators/Electronics/Sensors/DewPointMagnus/MainView.vue +++ b/src/components/Calculators/Electronics/Sensors/DewPointMagnus/MainView.vue @@ -73,7 +73,9 @@ // 'use strict' import Calc from 'src/misc/CalculatorEngineV2/Calc' - import { CalcVarNumeral } from 'src/misc/CalculatorEngineV2/CalcVarNumeral' + import {CalcVarNumeral} from 'src/misc/CalculatorEngineV2/CalcVarNumeral' + import {UnitMulti} from 'src/misc/CalculatorEngineV2/UnitMulti' + import {UnitFunc} from 'src/misc/CalculatorEngineV2/UnitFunc' import PresetValidators from 'src/misc/CalculatorEngineV2/PresetValidators' /* eslint-disable camelcase */ @@ -114,9 +116,18 @@ }, rawVal: '', units: [ - {text: '°C', value: 1e0} + new UnitMulti({ name: '°C', multi: 1e0 }), + new UnitFunc({ + name: 'F', + toUnit: function (baseValue) { + return baseValue * 1.8 + 32 + }, + fromUnit: function (unitValue) { + return (unitValue - 32) / 1.8 + } + }) ], - selUnit: 1e0, + defaultUnitName: '°C', roundTo: 4, validators: [ PresetValidators.IS_NUMBER @@ -148,9 +159,9 @@ }, rawVal: '', units: [ - {text: '%', value: 1e0} + new UnitMulti({ name: '%', multi: 1e0 }) ], - selUnit: 1e0, + defaultUnitName: '%', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -185,9 +196,18 @@ }, rawVal: '', units: [ - {text: '°C', value: 1e0} + new UnitMulti({ name: '°C', multi: 1e0 }), + new UnitFunc({ + name: 'F', + toUnit: function (baseValue) { + return baseValue * 1.8 + 32 + }, + fromUnit: function (unitValue) { + return (unitValue - 32) / 1.8 + } + }) ], - selUnit: 1e0, + defaultUnitName: '°C', roundTo: 4, validators: [ PresetValidators.IS_NUMBER @@ -206,9 +226,9 @@ eqn: () => {}, rawVal: '17.625', units: [ - {text: 'no unit', value: 1e0} + new UnitMulti({ name: 'no unit', multi: 1e0 }) ], - selUnit: 1e0, + defaultUnitName: 'no unit', roundTo: 5, validators: [ PresetValidators.IS_NUMBER @@ -227,9 +247,18 @@ eqn: () => {}, rawVal: '243.04', units: [ - {text: '°C', value: 1e0} + new UnitMulti({ name: '°C', multi: 1e0 }), + new UnitFunc({ + name: 'F', + toUnit: function (baseValue) { + return baseValue * 1.8 + 32 + }, + fromUnit: function (unitValue) { + return (unitValue - 32) / 1.8 + } + }) ], - selUnit: 1e0, + defaultUnitName: '°C', roundTo: 5, validators: [ PresetValidators.IS_NUMBER diff --git a/src/components/Calculators/Electronics/Sensors/NtcThermistor/Calc.js b/src/components/Calculators/Electronics/Sensors/NtcThermistor/Calc.js index fd561201..98fa2e2e 100644 --- a/src/components/Calculators/Electronics/Sensors/NtcThermistor/Calc.js +++ b/src/components/Calculators/Electronics/Sensors/NtcThermistor/Calc.js @@ -12,7 +12,7 @@ import MainView from './MainView' */ export var ntcThermistorTemperature = { displayName: 'NTC Thermistor', - description: 'Calculate the temperature/resistance (reference or actual), or beta-coefficient of NTC thermistors.', + description: 'Calculate the temperature, resistance (reference or actual), or beta-coefficient of NTC thermistors.', imagePath: require('./grid-icon.jpg'), category: [ 'Electronics', 'Sensors' ], tags: [ 'temperature', 'thermistor', 'ntc', 'negative', 'coefficient', 'sensor', 'resistor' ], diff --git a/src/components/Calculators/Electronics/Sensors/NtcThermistor/MainView.vue b/src/components/Calculators/Electronics/Sensors/NtcThermistor/MainView.vue index ed3acfe6..991971ef 100644 --- a/src/components/Calculators/Electronics/Sensors/NtcThermistor/MainView.vue +++ b/src/components/Calculators/Electronics/Sensors/NtcThermistor/MainView.vue @@ -105,6 +105,8 @@ import Calc from 'src/misc/CalculatorEngineV2/Calc' import {CalcVarNumeral} from 'src/misc/CalculatorEngineV2/CalcVarNumeral' + import {UnitMulti} from 'src/misc/CalculatorEngineV2/UnitMulti' + import {UnitFunc} from 'src/misc/CalculatorEngineV2/UnitFunc' import PresetValidators from 'src/misc/CalculatorEngineV2/PresetValidators' /* eslint-disable camelcase */ @@ -145,9 +147,9 @@ }, rawVal: '', units: [ - {text: 'no unit', value: 1e0} + new UnitMulti({name: 'no unit', multi: 1e0}) ], - selUnit: 1e0, + defaultUnitName: 'no unit', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -180,9 +182,12 @@ }, rawVal: '', units: [ - {text: 'Ω', value: 1e0} + new UnitMulti({name: 'mΩ', multi: 1e-3}), + new UnitMulti({name: 'Ω', multi: 1e0}), + new UnitMulti({name: 'kΩ', multi: 1e3}), + new UnitMulti({name: 'MΩ', multi: 1e6}) ], - selUnit: 1e0, + defaultUnitName: 'kΩ', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -215,9 +220,27 @@ }, rawVal: '', units: [ - {text: 'K', value: 1e0} + new UnitMulti({name: 'K', multi: 1e0}), + new UnitFunc({ + name: '°C', + toUnit: function (baseValue) { + return baseValue - 273.15 + }, + fromUnit: function (unitValue) { + return unitValue + 273.15 + } + }), + new UnitFunc({ + name: 'F', + toUnit: function (baseValue) { + return (baseValue - 273.15) * 1.8 + 32 + }, + fromUnit: function (unitValue) { + return ((unitValue - 32) / 1.8) + 273.15 + } + }) ], - selUnit: 1e0, + defaultUnitName: '°C', roundTo: 4, validators: [ PresetValidators.IS_NUMBER @@ -249,9 +272,12 @@ }, rawVal: '', units: [ - {text: 'Ω', value: 1e0} + new UnitMulti({name: 'mΩ', multi: 1e-3}), + new UnitMulti({name: 'Ω', multi: 1e0}), + new UnitMulti({name: 'kΩ', multi: 1e3}), + new UnitMulti({name: 'MΩ', multi: 1e6}) ], - selUnit: 1e0, + defaultUnitName: 'kΩ', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, @@ -284,9 +310,27 @@ }, rawVal: '', units: [ - {text: 'K', value: 1e0} + new UnitMulti({name: 'K', multi: 1e0}), + new UnitFunc({ + name: '°C', + toUnit: function (baseValue) { + return baseValue - 273.15 + }, + fromUnit: function (unitValue) { + return unitValue + 273.15 + } + }), + new UnitFunc({ + name: 'F', + toUnit: function (baseValue) { + return (baseValue - 273.15) * 1.8 + 32 + }, + fromUnit: function (unitValue) { + return ((unitValue - 32) / 1.8) + 273.15 + } + }) ], - selUnit: 1e0, + defaultUnitName: '°C', roundTo: 4, validators: [ PresetValidators.IS_NUMBER diff --git a/src/components/Calculators/Software/Crc/CustomCrcAlgorithm.vue b/src/components/Calculators/Software/Crc/CustomCrcAlgorithm.vue index 4dfeecda..746ae1af 100644 --- a/src/components/Calculators/Software/Crc/CustomCrcAlgorithm.vue +++ b/src/components/Calculators/Software/Crc/CustomCrcAlgorithm.vue @@ -41,6 +41,7 @@ import {CalcVarNumeral} from 'src/misc/CalculatorEngineV2/CalcVarNumeral' import {CalcVarString, CalcVarStringPresetValidators} from 'src/misc/CalculatorEngineV2/CalcVarString' import {CalcVarCheckbox} from 'src/misc/CalculatorEngineV2/CalcVarCheckbox' + import {UnitMulti} from 'src/misc/CalculatorEngineV2/UnitMulti' import PresetValidators from 'src/misc/CalculatorEngineV2/PresetValidators' import {CustomValidator} from 'src/misc/CalculatorEngineV2/CustomValidator' import {CrcGeneric} from 'src/misc/Crc/CrcGeneric' @@ -70,9 +71,9 @@ }, rawVal: '', units: [ - {text: 'no unit', value: 1e0} + new UnitMulti({name: 'no unit', multi: 1e0}) ], - selUnit: 1e0, + defaultUnitName: 'no unit', roundTo: 4, validators: [ PresetValidators.IS_NUMBER, diff --git a/src/main.js b/src/main.js index 635dbd4d..135d0d0e 100644 --- a/src/main.js +++ b/src/main.js @@ -6,6 +6,8 @@ import App from './App' Vue.use(Vuex) +// vue-material is used for md-tooltips, which display +// calculator variable info import VueMaterial from 'vue-material' import 'vue-material/dist/vue-material.css' Vue.use(VueMaterial) @@ -14,13 +16,8 @@ Vue.use(VueMaterial) import vSelect from 'vue-select' Vue.component(vSelect) -// import BootstrapVue from 'bootstrap-vue' -// Globally register bootstrap-vue components -// Vue.use(BootstrapVue) -// Loading of bootstrap CSS is required for BootstrapVue to work correctly -// import 'bootstrap/dist/css/bootstrap.css' - -// KeenUI is used for the tabs +// KeenUI is used for the collapsable "Info" +// sections on each calculator import KeenUI from 'keen-ui' Vue.use(KeenUI) import 'keen-ui/dist/keen-ui.css' @@ -37,15 +34,15 @@ Vue.use(ElementUI) // =========================================== // // ==== CALCULATOR COMPONENT REGISTRATION ==== // // =========================================== // -import CalcValue from 'src/misc/CalculatorEngineV2/CalcValue' +import CalcValue from 'misc/CalculatorEngineV2/view/CalcValue.vue' Vue.component('calc-value', CalcValue) -import CalcValueAndUnit from 'src/misc/CalculatorEngineV2/CalcValueAndUnit' +import CalcValueAndUnit from 'misc/CalculatorEngineV2/view/CalcValueAndUnit.vue' Vue.component('calc-value-and-unit', CalcValueAndUnit) -import CalcUnits from 'src/misc/CalculatorEngineV2/CalcUnits' +import CalcUnits from 'misc/CalculatorEngineV2/view/CalcUnits.vue' Vue.component('calc-units', CalcUnits) -import CalcVarString from 'src/misc/CalculatorEngineV2/view/CalcVarString' +import CalcVarString from 'src/misc/CalculatorEngineV2/view/CalcVarString.vue' Vue.component('calc-var-string', CalcVarString) -import CalcVarCheckbox from 'src/misc/CalculatorEngineV2/view/CalcVarCheckbox' +import CalcVarCheckbox from 'src/misc/CalculatorEngineV2/view/CalcVarCheckbox.vue' Vue.component('calc-var-checkbox', CalcVarCheckbox) /* eslint-disable no-unused-vars */ @@ -54,38 +51,121 @@ const store = new Vuex.Store({ count: 0, showLeftSideBar: false, showCalculatorSelectionOverlay: false, + + // Complete list of calculators that the user can open. + // These are presented to the user, but filtered first. availableCalcs: [], + + // This is updated whenever the search text is changed. + filteredAvailableCalcs: [], openCalcs: [], - activeTabId: '' + activeTabId: '', + searchText: '' }, mutations: { - increment (state, payload) { - state.count += payload.amount - }, showLeftSideBar (state, payload) { state.showLeftSideBar = payload.trueFalse }, showCalculatorSelectionOverlay (state, payload) { state.showCalculatorSelectionOverlay = payload.trueFalse }, + registerCalc (state, payload) { + state.availableCalcs.push(payload) + }, openCalculator (state, payload) { - // console.log('openCalculator() called. payload.name = "' + payload.name + '".') + // Find a unique ID to use + var maxId = 0 + state.openCalcs.forEach((calc, index) => { + if (calc.uniqueId > maxId) { + maxId = calc.uniqueId + } + }) + const newUniqueId = maxId + 1 + state.openCalcs.push({ name: payload.name, componentName: payload.componentName, // Unique ID is used as a unique tab ID - uniqueId: state.openCalcs.length + uniqueId: newUniqueId }) }, - registerCalc (state, payload) { - // console.log('registerCalc() called with payload =') - // console.log(payload) - state.availableCalcs.push(payload) - }, setNewCalcAsOpenTab (state, payload) { // console.log('setNewCalcAsOpenTab() called with payload =') // console.log(payload) state.activeTabId = state.openCalcs[state.openCalcs.length - 1].uniqueId + }, + closeCalculator (state, payload) { + console.log('closeCalculator() called with payload.uniqueId = ' + payload.uniqueId) + if (!payload.uniqueId) { + throw new Error('Please provide payload.uniqueId to closeCalculator().') + } + // We need to search through the open calculators and find the one which matches the + // provided ID + if (state.activeTabId === payload.uniqueId) { + console.log('Closing currently active tab.') + // Since the user wants to close the currently active tab, we need to find + // the next best calculator tab to set as the active tab + state.openCalcs.forEach((calc, index) => { + console.log('calc =') + console.log(calc) + if (calc.uniqueId === payload.uniqueId) { + console.log('Calculator found!') + let nextCalc = state.openCalcs[index + 1] || state.openCalcs[index - 1] + console.log('nextCalc =') + console.log(nextCalc) + if (nextCalc) { + state.activeTabId = nextCalc.uniqueId + } + } + }) + } + + // Now that we have selected the next best calculator that is going to remain open, + // close the requested calculator by removing it from the openCalcs array + state.openCalcs = state.openCalcs.filter(calc => calc.uniqueId !== payload.uniqueId) + }, + setSearchText (state, payload) { + state.searchText = payload + }, + updateFilteredAvailableCalcs (state, payload) { + // Update the filtered available calculators. If the search text is '' (i.e. + // empty), return all the calculators. + if (state.searchText === '') { + state.filteredAvailableCalcs = state.availableCalcs + return + } + state.filteredAvailableCalcs = state.availableCalcs.filter(calc => { + // Create regex pattern from search text + var regex = new RegExp(state.searchText, 'gi') + // Search in calculator title (display name) + if (calc.displayName.match(regex)) return true + // Search through the tags + for (var tag of calc.tags) { + if (tag.match(regex)) return true + } + }) + } + }, + actions: { + /** + * Call this to register a calculator with the app. This is typically done at + * start-up. + * @param context + * @param value The calculator you wish to register. + */ + registerCalc (context, value) { + context.commit('registerCalc', value) + context.commit('updateFilteredAvailableCalcs') + }, + /** + * This will set the search text, and also update the filteredAvailableCalcs variable, + * depending on the search text. + * @param context + * @param value + */ + setSearchText (context, value) { + context.commit('setSearchText', value) + context.commit('updateFilteredAvailableCalcs') } } }) diff --git a/src/misc/CalculatorEngineV2/Calc.js b/src/misc/CalculatorEngineV2/Calc.js index 544fe08d..5cb9a989 100644 --- a/src/misc/CalculatorEngineV2/Calc.js +++ b/src/misc/CalculatorEngineV2/Calc.js @@ -18,7 +18,6 @@ export default class Calc { } getVar = (name) => { -// console.log('getVar() called with name = ' + name) var variable = this.calcVars.find((element) => { return element.name === name }) diff --git a/src/misc/CalculatorEngineV2/CalcVarNumeral.js b/src/misc/CalculatorEngineV2/CalcVarNumeral.js index 9e213cf9..f034ee47 100644 --- a/src/misc/CalculatorEngineV2/CalcVarNumeral.js +++ b/src/misc/CalculatorEngineV2/CalcVarNumeral.js @@ -1,10 +1,23 @@ import CalcVar from './CalcVar' +import {UnitMulti} from './UnitMulti' +import {UnitFunc} from './UnitFunc' export class CalcVarNumeral extends CalcVar { constructor (initObj) { super(initObj) + + // ============================================ // + // =================== UNITS ================== // + // ============================================ // + + // CalcVarNumeral is the only calculator variable type which + // has unit support this.units = initObj.units - this.selUnit = initObj.selUnit + + if (!initObj.defaultUnitName) throw new Error('Please provide a default unit name via initObj.defaultUnitName to CalcVarNumeral.constructor() for variable "' + initObj.name + '".') + this.selUnitName = initObj.defaultUnitName + console.log('this.selUnitName = ' + this.selUnitName) + this.selUnit = this.findUnitFromName(this.selUnitName) // ============================================ // // ================= ROUNDING ================= // @@ -30,11 +43,16 @@ export class CalcVarNumeral extends CalcVar { * Designed to be called by vue once this.selUnit has been changed. */ onUnitChange = () => { - // console.log('onUnitsChange() called.') + console.log('CalcVarNumeral.onUnitChange() called.') + console.log('this.selUnitName = ' + this.selUnitName) + + this.selUnit = this.findUnitFromName(this.selUnitName) + console.log('this.selUnit =') + console.log(this.selUnit) if (this.typeEqn() === 'input') { // Recalculate raw value from displayed value - this.rawVal = this.dispVal * this.selUnit + this.calcRawValFromDispVal() this.validate() } @@ -45,7 +63,12 @@ export class CalcVarNumeral extends CalcVar { if (this.rawVal === '') { this.dispVal = '' } else { - var unRoundedDispVal = this.rawVal / this.selUnit + var unRoundedDispVal + if (this.selUnit instanceof UnitMulti) { + unRoundedDispVal = this.rawVal / this.selUnit.multi + } else if (this.selUnit instanceof UnitFunc) { + unRoundedDispVal = this.selUnit.toUnit(this.rawVal) + } else throw new Error('The class type of this.selUnit is not recognised!') // This uses 'significant figure' style rounding var roundedDispVal = unRoundedDispVal.toPrecision(this.roundTo) @@ -53,13 +76,26 @@ export class CalcVarNumeral extends CalcVar { } } + calcRawValFromDispVal = () => { + // We have to take different actions depending on the + // type of units currently selected + if (this.selUnit instanceof UnitMulti) { + this.rawVal = parseFloat(this.dispVal) * parseFloat(this.selUnit.multi) + } else if (this.selUnit instanceof UnitFunc) { + this.rawVal = this.selUnit.fromUnit(parseFloat(this.dispVal)) + } else throw new Error('The class type of this.selUnit is not recognised!') + } + reCalc = () => { - console.log('CalcVarNumerical.reCalc() called for "' + this.name + '".') + // console.log('CalcVarNumerical.reCalc() called for "' + this.name + '".') if (this.typeEqn() !== 'output') { throw new Error('reCalc() called for variable that was not an output.') } + // Raw value is calculated using the provided equation. + // Equation takes no inputs, it gets access to other calculator variables + // through the lambda scope this.rawVal = this.eqn() this.calcDispValFromRawVal() @@ -70,13 +106,27 @@ export class CalcVarNumeral extends CalcVar { * Designed to be called by vue once this.dispVal has been changed. */ onDispValChange = () => { - // console.log('onDispValChange() called.') - // console.log('this.dispVal =' + this.dispVal) - - this.rawVal = parseFloat(this.dispVal) * parseFloat(this.selUnit) - // console.log('this.rawVal = ' + this.rawVal) - + this.calcRawValFromDispVal() this.validate() this.triggerReCalcOutputsAndValidate() } + + findUnitFromName = (unitName) => { + // console.log('CalcVarNumeral.findUnitFromName() called with unitName = ' + unitName) + var foundUnit = null + this.units.forEach(function (element) { + // console.log(element) + if (element.name === unitName) { + // console.log('Unit found! unit =') + // console.log(element) + foundUnit = element + } + }) + + if (foundUnit) { + return foundUnit + } else { + throw new Error('Could not find unit with name "' + unitName + '" in calculator variable "' + this.name + '".') + } + } } diff --git a/src/misc/CalculatorEngineV2/Unit.js b/src/misc/CalculatorEngineV2/Unit.js new file mode 100644 index 00000000..9e133abe --- /dev/null +++ b/src/misc/CalculatorEngineV2/Unit.js @@ -0,0 +1,14 @@ +export class Unit { + constructor (initObj) { + // console.log('Unit.constructor() called.') + + if (this.constructor === Unit) { + throw new TypeError('Abstract class "Unit" cannot be instantiated directly.') + } + + // The name is used both as the binding value and the displayed text + // with a vue select UI object. + if (!initObj.name) throw new Error('Please provide a unit name via initObj.name to Unit.constructor().') + this.name = initObj.name + } +} diff --git a/src/misc/CalculatorEngineV2/UnitFunc.js b/src/misc/CalculatorEngineV2/UnitFunc.js new file mode 100644 index 00000000..22c912c3 --- /dev/null +++ b/src/misc/CalculatorEngineV2/UnitFunc.js @@ -0,0 +1,9 @@ +import {Unit} from './Unit' + +export class UnitFunc extends Unit { + constructor (initObj) { + super(initObj) + this.toUnit = initObj.toUnit + this.fromUnit = initObj.fromUnit + } +} diff --git a/src/misc/CalculatorEngineV2/UnitMulti.js b/src/misc/CalculatorEngineV2/UnitMulti.js new file mode 100644 index 00000000..23e95d1e --- /dev/null +++ b/src/misc/CalculatorEngineV2/UnitMulti.js @@ -0,0 +1,9 @@ +import {Unit} from './Unit' + +export class UnitMulti extends Unit { + constructor (initObj) { + super(initObj) + if (typeof initObj.multi !== 'number') throw new Error('Please provide a multiplier (number) via initObj.multi to UnitMulti.constructor(). this.name = ' + this.name) + this.multi = initObj.multi + } +} diff --git a/src/misc/CalculatorEngineV2/style.css b/src/misc/CalculatorEngineV2/style.css index d07435bb..4d955ffd 100644 --- a/src/misc/CalculatorEngineV2/style.css +++ b/src/misc/CalculatorEngineV2/style.css @@ -1,4 +1,6 @@ -input { +/* The variable-value class is applied to the input object of CalcValue, +CalcValueAndUnit, and CalcVarString */ +input.variable-value { border-style: solid; border-radius: 2px; diff --git a/src/misc/CalculatorEngineV2/CalcUnits.vue b/src/misc/CalculatorEngineV2/view/CalcUnits.vue similarity index 84% rename from src/misc/CalculatorEngineV2/CalcUnits.vue rename to src/misc/CalculatorEngineV2/view/CalcUnits.vue index 691ee1e0..9cb446c4 100644 --- a/src/misc/CalculatorEngineV2/CalcUnits.vue +++ b/src/misc/CalculatorEngineV2/view/CalcUnits.vue @@ -1,16 +1,16 @@ diff --git a/src/misc/UnitConversionConstants/UnitConversionConstants.js b/src/misc/UnitConversionConstants/UnitConversionConstants.js index c9de334f..eea64f29 100644 --- a/src/misc/UnitConversionConstants/UnitConversionConstants.js +++ b/src/misc/UnitConversionConstants/UnitConversionConstants.js @@ -1,8 +1,13 @@ -export class UnitConversionConstants { +class UnitConversionConstants { constructor () { this.METERS_PER_INCH = 25.4 / 1000.0 this.METERS_PER_MILS = this.METERS_PER_INCH / 1000.0 this.COPPER_THICKNESS_M_PER_OZ = 0.0000350012 + + this.M2_PER_MIL2 = this.METERS_PER_MILS * this.METERS_PER_MILS + + this.THERMAL_CONDUCTIVITY_WATT_nMETER_nKELVIN_PER_BTU_nHOUR_nFT_nDEGF = 1.73 // eslint-disable-line camelcase } } +export let unitConversionConstants = new UnitConversionConstants() diff --git a/test/e2e/specs/test.js b/test/e2e/specs/test.js index a7b1bd92..6fb00cd6 100644 --- a/test/e2e/specs/test.js +++ b/test/e2e/specs/test.js @@ -11,9 +11,7 @@ module.exports = { browser .url(devServer) .waitForElementVisible('#app', 5000) - .assert.elementPresent('.hello') - .assert.containsText('h1', 'Welcome to Your Vue.js App') - .assert.elementCount('img', 1) + .assert.elementPresent('#no-calc-screen') .end() } } diff --git a/test/unit/karma.conf.js b/test/unit/karma.conf.js index 3211fb6f..d6a43a41 100644 --- a/test/unit/karma.conf.js +++ b/test/unit/karma.conf.js @@ -14,7 +14,10 @@ module.exports = function (config) { browsers: ['PhantomJS'], frameworks: ['mocha', 'sinon-chai'], reporters: ['spec', 'coverage'], - files: ['./index.js'], + files: [ + '../../node_modules/phantomjs-polyfill-find/find-polyfill.js', // This find polyfill is required because as of 2017-03, phantom-js does not support the array.find() prototype. + './index.js' + ], preprocessors: { './index.js': ['webpack', 'sourcemap'] }, diff --git a/test/unit/specs/CrcCatalogue.spec.js b/test/unit/specs/CrcCatalogue.spec.js index b854a77c..ba79f18c 100644 --- a/test/unit/specs/CrcCatalogue.spec.js +++ b/test/unit/specs/CrcCatalogue.spec.js @@ -28,9 +28,7 @@ describe('CrcCatalogue object tests.', function () { describe('CrcCatalogue CRC check value tests.', function () { it('Compare CRC algorithm to check value.', function () { - console.log('to be implemented') for (var [key, value] of crcCatalogue.presetCrcAlgorithms) { - console.log(key + ' = ' + value) // Create a CRC engine with this algorithm info var crcGeneric = new CrcGeneric({ name: value.name, @@ -42,15 +40,11 @@ describe('CrcCatalogue CRC check value tests.', function () { finalXorValue: value.finalXorValue, checkValue: value.checkValue }) - console.log('crcGeneric =') - console.log(crcGeneric) var dataArray = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] for (let data of dataArray) { crcGeneric.update(data.charCodeAt()) } var result = crcGeneric.getValue().toJSNumber() - console.log(result) - expect(result).to.equal(value.checkValue.toJSNumber()) } }) diff --git a/test/unit/specs/Hello.spec.js b/test/unit/specs/Hello.spec.js index a1013018..a71ae070 100644 --- a/test/unit/specs/Hello.spec.js +++ b/test/unit/specs/Hello.spec.js @@ -1,11 +1,41 @@ // import Vue from 'vue' -// import Hello from 'src/components/Hello' +// import Vuex from 'vuex' +// Vue.use(Vuex) +// +// import CalcValue from 'src/misc/CalculatorEngineV2/CalcValue' +// Vue.component('calc-value', CalcValue) +// import CalcValueAndUnit from 'src/misc/CalculatorEngineV2/CalcValueAndUnit' +// Vue.component('calc-value-and-unit', CalcValueAndUnit) +// import CalcUnits from 'src/misc/CalculatorEngineV2/CalcUnits' +// Vue.component('calc-units', CalcUnits) +// import CalcVarString from 'src/misc/CalculatorEngineV2/view/CalcVarString' +// Vue.component('calc-var-string', CalcVarString) +// import CalcVarCheckbox from 'src/misc/CalculatorEngineV2/view/CalcVarCheckbox' +// Vue.component('calc-var-checkbox', CalcVarCheckbox) +// +// import VueMaterial from 'vue-material' +// import 'vue-material/dist/vue-material.css' +// Vue.use(VueMaterial) +// +// import KeenUI from 'keen-ui' +// Vue.use(KeenUI) +// import 'keen-ui/dist/keen-ui.css' +// +// // require('phantomjs-polyfill-find') +// +// import MainView from 'src/components/Calculators/Electronics/Basic/OhmsLaw/MainView' // // describe('Hello.vue', () => { // it('should render correct contents', () => { -// const Constructor = Vue.extend(Hello) +// const Constructor = Vue.extend(MainView) +// console.log('Constructor = ' + Constructor) // const vm = new Constructor().$mount() -// expect(vm.$el.querySelector('.hello h1').textContent) -// .to.equal('Welcome to Your Vue.js App') +// vm.$el.querySelector('#voltage input').textContent = '1' +// console.log('#voltage input =') +// console.log(vm.$el.querySelector('#voltage input')) +// vm.$el.querySelector('#current input').textContent = '2' +// vm.$el.querySelector('#voltage input').dispatchEvent(new Event('change')) +// expect(vm.$el.querySelector('#resistance input').textContent).to.equal('0.5') +// console.log('TEST FINISHED') // }) // })