mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-11-01 18:53:59 -04:00
* pin editor buttons on scroll * scaler scratch * fix langauge assignment 1st pass * set lang on navigate * refactor/breakup router * unify style for language selectro * refactor/code-cleanup * refactor/page specific components to page folder * Fix time card layout issue * fix timecard display * update mobile cards / fix overflow errors Co-authored-by: hay-kot <hay-kot@pm.me>
167 lines
4.3 KiB
JavaScript
167 lines
4.3 KiB
JavaScript
export const recipeNumber = function(number) {
|
|
const match = number.match(
|
|
/^(?:(\d+)|(?:(\d+)(?: | ))?(?:(\d+)\/(\d+))?)$/
|
|
);
|
|
if (!match || !match[0] || match[4] == "0") {
|
|
throw `Invalid number: "${number}".`;
|
|
}
|
|
this.wholeNumber = +(match[1] || match[2]);
|
|
this.numerator = +match[3];
|
|
this.denominator = +match[4];
|
|
};
|
|
|
|
/**
|
|
* Determines if the number is a fraction.
|
|
* @this {recipeNumber}
|
|
* @return {boolean} If the number is a fraction.
|
|
*/
|
|
recipeNumber.prototype.isFraction = function() {
|
|
return !!(this.numerator && this.denominator);
|
|
};
|
|
|
|
/**
|
|
* Determines if the fraction is proper, which is defined as
|
|
* the numerator being strictly less than the denominator.
|
|
* @this {recipeNumber}
|
|
* @return {boolean} If the fraction is proper.
|
|
*/
|
|
recipeNumber.prototype.isProperFraction = function() {
|
|
return this.numerator < this.denominator;
|
|
};
|
|
|
|
/**
|
|
* Determines if the fraction is improper, which is defined as
|
|
* the numerator being greater than or equal to the denominator.
|
|
* @this {recipeNumber}
|
|
* @return {boolean} If the fraction is improper.
|
|
*/
|
|
recipeNumber.prototype.isImproperFraction = function() {
|
|
return this.numerator >= this.denominator;
|
|
};
|
|
|
|
/**
|
|
* Determines if the fraction is mixed, which is defined as
|
|
* a whole number with a proper fraction.
|
|
* @this {recipeNumber}
|
|
* @return {boolean} If the fraction is mixed.
|
|
*/
|
|
recipeNumber.prototype.isMixedFraction = function() {
|
|
return this.isProperFraction() && !isNaN(this.wholeNumber);
|
|
};
|
|
|
|
/**
|
|
* Simplifies fractions. Examples:
|
|
* 3/2 = 1 1/2
|
|
* 4/2 = 2
|
|
* 1 3/2 = 2 1/2
|
|
* 0/1 = 0
|
|
* 1 0/1 = 1
|
|
* @this {recipeNumber}
|
|
* @return {recipeNumber} The instance.
|
|
*/
|
|
recipeNumber.prototype.simplifyFraction = function() {
|
|
if (this.isImproperFraction()) {
|
|
this.wholeNumber |= 0;
|
|
this.wholeNumber += Math.floor(this.numerator / this.denominator);
|
|
const modulus = this.numerator % this.denominator;
|
|
if (modulus) {
|
|
this.numerator = modulus;
|
|
} else {
|
|
this.numerator = this.denominator = NaN;
|
|
}
|
|
} else if (this.numerator == 0) {
|
|
this.wholeNumber |= 0;
|
|
this.numerator = this.denominator = NaN;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Reduces a fraction. Examples:
|
|
* 2/6 = 1/3
|
|
* 6/2 = 3/1
|
|
* @this {recipeNumber}
|
|
* @return {recipeNumber} The instance.
|
|
*/
|
|
recipeNumber.prototype.reduceFraction = function() {
|
|
if (this.isFraction()) {
|
|
const gcd = recipeNumber.gcd(this.numerator, this.denominator);
|
|
this.numerator /= gcd;
|
|
this.denominator /= gcd;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Converts proper fractions to improper fractions. Examples:
|
|
* 1 1/2 = 3/2
|
|
* 3/2 = 3/2
|
|
* 1/2 = 1/2
|
|
* 2 = 2
|
|
*
|
|
* @this {recipeNumber}
|
|
* @return {recipeNumber} The instance.
|
|
*/
|
|
recipeNumber.prototype.toImproperFraction = function() {
|
|
if (!isNaN(this.wholeNumber)) {
|
|
this.numerator |= 0;
|
|
this.denominator = this.denominator || 1;
|
|
this.numerator += this.wholeNumber * this.denominator;
|
|
this.wholeNumber = NaN;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Multiplies the number by some decimal value.
|
|
* @param {number} multiplier The multiplier.
|
|
* @this {recipeNumber}
|
|
* @return {recipeNumber} The instance.
|
|
*/
|
|
recipeNumber.prototype.multiply = function(multiplier) {
|
|
this.toImproperFraction();
|
|
this.numerator *= multiplier;
|
|
return this.reduceFraction().simplifyFraction();
|
|
};
|
|
|
|
/**
|
|
* Gets a string representation of the number.
|
|
* @this {recipeNumber}
|
|
* @return {string} The string representation of the number.
|
|
*/
|
|
recipeNumber.prototype.toString = function() {
|
|
let number = "";
|
|
let fraction = "";
|
|
if (!isNaN(this.wholeNumber)) {
|
|
number += this.wholeNumber;
|
|
}
|
|
if (this.isFraction()) {
|
|
fraction = `${this.numerator}/${this.denominator}`;
|
|
}
|
|
if (number && fraction) {
|
|
number += ` ${fraction}`;
|
|
}
|
|
return number || fraction;
|
|
};
|
|
|
|
/**
|
|
* Gets a numeric representation of the number.
|
|
* @this {recipeNumber}
|
|
* @return {number} The numeric representation of the number.
|
|
*/
|
|
recipeNumber.prototype.valueOf = function() {
|
|
let value = this.wholeNumber || 0;
|
|
value += this.numerator / this.denominator || 0;
|
|
return value;
|
|
};
|
|
|
|
/**
|
|
* Euclid's algorithm to find the greatest common divisor of two numbers.
|
|
* @param {number} a One number.
|
|
* @param {number} b Another number.
|
|
* @return {number} The GCD of the numbers.
|
|
*/
|
|
recipeNumber.gcd = function gcd(a, b) {
|
|
return b ? recipeNumber.gcd(b, a % b) : a;
|
|
};
|