|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekadd(a, b) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number') { |
|
|
throw new Error('nekadd: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
return a + b; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function neksub(a, b) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number') { |
|
|
throw new Error('neksub: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
return a - b; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekmult(a, b) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number') { |
|
|
throw new Error('nekmult: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
return a * b; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekdiv(a, b) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number') { |
|
|
throw new Error('nekdiv: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
if (b === 0) { |
|
|
throw new Error('nekdiv: Division par zéro impossible.'); |
|
|
} |
|
|
return a / b; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekIsPairOuImpair(number) { |
|
|
if (typeof number !== 'number') { |
|
|
throw new Error('nekIsPairOuImpair: L\'argument doit être un nombre.'); |
|
|
} |
|
|
|
|
|
if (!Number.isInteger(number)) { |
|
|
return `Le nombre ${number} n'est pas un entier. Il n'est ni pair ni impair.`; |
|
|
} |
|
|
if (number % 2 === 0) { |
|
|
return `Le nombre ${number} est pair.`; |
|
|
} else { |
|
|
return `Le nombre ${number} est impair.`; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekorandom(min, max) { |
|
|
if (typeof min !== 'number' || typeof max !== 'number') { |
|
|
throw new Error('nekorandom: Les arguments min et max doivent être des nombres.'); |
|
|
} |
|
|
if (min > max) { |
|
|
throw new Error('nekorandom: La valeur min ne peut pas être supérieure à max.'); |
|
|
} |
|
|
|
|
|
const ceilMin = Math.ceil(min); |
|
|
const floorMax = Math.floor(max); |
|
|
|
|
|
return Math.floor(Math.random() * (floorMax - ceilMin + 1)) + ceilMin; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekofibona(n) { |
|
|
if (typeof n !== 'number' || !Number.isInteger(n) || n < 0) { |
|
|
throw new Error('nekofibona: L\'argument doit être un entier non négatif.'); |
|
|
} |
|
|
if (n === 0) return 0; |
|
|
if (n === 1) return 1; |
|
|
|
|
|
let a = 0, b = 1; |
|
|
for (let i = 2; i <= n; i++) { |
|
|
let temp = a + b; |
|
|
a = b; |
|
|
b = temp; |
|
|
} |
|
|
return b; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekpremier(number) { |
|
|
if (typeof number !== 'number' || !Number.isInteger(number)) { |
|
|
throw new Error('nekpremier: L\'argument doit être un entier.'); |
|
|
} |
|
|
if (number <= 1) return false; |
|
|
if (number <= 3) return true; |
|
|
if (number % 2 === 0 || number % 3 === 0) return false; |
|
|
|
|
|
|
|
|
for (let i = 5; i * i <= number; i = i + 6) { |
|
|
if (number % i === 0 || number % (i + 2) === 0) |
|
|
return false; |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekopi = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
valeur: Math.PI, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
circonference: function(rayon) { |
|
|
if (typeof rayon !== 'number' || rayon < 0) { |
|
|
throw new Error('nekopi.circonference: Le rayon doit être un nombre positif.'); |
|
|
} |
|
|
return 2 * Math.PI * rayon; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
aireCercle: function(rayon) { |
|
|
if (typeof rayon !== 'number' || rayon < 0) { |
|
|
throw new Error('nekopi.aireCercle: Le rayon doit être un nombre positif.'); |
|
|
} |
|
|
return Math.PI * rayon * rayon; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
degresEnRadians: function(degres) { |
|
|
if (typeof degres !== 'number') { |
|
|
throw new Error('nekopi.degresEnRadians: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return degres * (Math.PI / 180); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
radiansEnDegres: function(radians) { |
|
|
if (typeof radians !== 'number') { |
|
|
throw new Error('nekopi.radiansEnDegres: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return radians * (180 / Math.PI); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekracine(number) { |
|
|
if (typeof number !== 'number' || number < 0) { |
|
|
throw new Error('nekracine: L\'argument doit être un nombre non négatif.'); |
|
|
} |
|
|
return Math.sqrt(number); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekodouble(number) { |
|
|
if (typeof number !== 'number') { |
|
|
throw new Error('nekodouble: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return number * 2; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekomoitie(number) { |
|
|
if (typeof number !== 'number') { |
|
|
throw new Error('nekomoitie: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return number / 2; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekdegres = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enDegres: function(radians) { |
|
|
if (typeof radians !== 'number') { |
|
|
throw new Error('nekdegres.enDegres: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return radians * (180 / Math.PI); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enRadians: function(degres) { |
|
|
if (typeof degres !== 'number') { |
|
|
throw new Error('nekdegres.enRadians: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return degres * (Math.PI / 180); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sinus: function(degres) { |
|
|
if (typeof degres !== 'number') { |
|
|
throw new Error('nekdegres.sinus: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return Math.sin(this.enRadians(degres)); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cosinus: function(degres) { |
|
|
if (typeof degres !== 'number') { |
|
|
throw new Error('nekdegres.cosinus: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return Math.cos(this.enRadians(degres)); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tangente: function(degres) { |
|
|
if (typeof degres !== 'number') { |
|
|
throw new Error('nekdegres.tangente: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return Math.tan(this.enRadians(degres)); |
|
|
}, |
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekFacteurs(number) { |
|
|
if (typeof number !== 'number' || !Number.isInteger(number) || number <= 1) { |
|
|
throw new Error('nekFacteurs: L\'argument doit être un entier positif supérieur à 1.'); |
|
|
} |
|
|
const facteurs = []; |
|
|
let diviseur = 2; |
|
|
|
|
|
while (number > 1) { |
|
|
while (number % diviseur === 0) { |
|
|
facteurs.push(diviseur); |
|
|
number /= diviseur; |
|
|
} |
|
|
diviseur++; |
|
|
} |
|
|
return facteurs; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekopuissance(base, exposant) { |
|
|
if (typeof base !== 'number' || typeof exposant !== 'number') { |
|
|
throw new Error('nekopuissance: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
return Math.pow(base, exposant); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekmed(arr) { |
|
|
if (!Array.isArray(arr) || arr.some(num => typeof num !== 'number')) { |
|
|
throw new Error('nekmed: L\'argument doit être un tableau de nombres.'); |
|
|
} |
|
|
if (arr.length === 0) { |
|
|
throw new Error('nekmed: Le tableau ne peut pas être vide.'); |
|
|
} |
|
|
const sorted = [...arr].sort((a, b) => a - b); |
|
|
const mid = Math.floor(sorted.length / 2); |
|
|
return sorted.length % 2 !== 0 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekmoy(arr) { |
|
|
if (!Array.isArray(arr) || arr.some(num => typeof num !== 'number')) { |
|
|
throw new Error('nekmoy: L\'argument doit être un tableau de nombres.'); |
|
|
} |
|
|
if (arr.length === 0) { |
|
|
throw new Error('nekmoy: Le tableau ne peut pas être vide.'); |
|
|
} |
|
|
return arr.reduce((sum, num) => sum + num, 0) / arr.length; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const neky = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
metersToKilometers: function(meters) { |
|
|
if (typeof meters !== 'number') { |
|
|
throw new Error('neky.metersToKilometers: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return meters / 1000; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
kilometersToMeters: function(kilometers) { |
|
|
if (typeof kilometers !== 'number') { |
|
|
throw new Error('neky.kilometersToMeters: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return kilometers * 1000; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const neklet = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
kilosToTonnes: function(kilos) { |
|
|
if (typeof kilos !== 'number') { |
|
|
throw new Error('neklet.kilosToTonnes: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return kilos / 1000; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tonnesToKilos: function(tonnes) { |
|
|
if (typeof tonnes !== 'number') { |
|
|
throw new Error('neklet.tonnesToKilos: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return tonnes * 1000; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gramsToKilograms: function(grams) { |
|
|
if (typeof grams !== 'number') { |
|
|
throw new Error('neklet.gramsToKilograms: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return grams / 1000; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
kilogramsToGrams: function(kilograms) { |
|
|
if (typeof kilograms !== 'number') { |
|
|
throw new Error('neklet.kilogramsToGrams: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return kilograms * 1000; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
customConversion: function(value, factor) { |
|
|
if (typeof value !== 'number' || typeof factor !== 'number') { |
|
|
throw new Error('neklet.customConversion: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
return value * factor; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekpourcentage(total, pourcentage) { |
|
|
if (typeof total !== 'number' || typeof pourcentage !== 'number') { |
|
|
throw new Error('nekpourcentage: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
return (total * pourcentage) / 100; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nektalor = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hypotenuse: function(a, b) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number' || a <= 0 || b <= 0) { |
|
|
throw new Error('nektalor.hypotenuse: Les arguments doivent être des nombres positifs.'); |
|
|
} |
|
|
return Math.sqrt(a * a + b * b); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
coteAdjacent: function(hypotenuse, cote) { |
|
|
if (typeof hypotenuse !== 'number' || typeof cote !== 'number' || hypotenuse <= 0 || cote <= 0) { |
|
|
throw new Error('nektalor.coteAdjacent: Les arguments doivent être des nombres positifs.'); |
|
|
} |
|
|
if (hypotenuse <= cote) { |
|
|
throw new Error('nektalor.coteAdjacent: L\'hypoténuse doit être plus grande que le côté.'); |
|
|
} |
|
|
return Math.sqrt(hypotenuse * hypotenuse - cote * cote); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nektales = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proportionnalite: function(a, b, c) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number' || typeof c !== 'number') { |
|
|
throw new Error('nektales.proportionnalite: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
if (b === 0) { |
|
|
throw new Error('nektales.proportionnalite: Le deuxième terme ne peut pas être zéro.'); |
|
|
} |
|
|
return (b * c) / a; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
verifierProportionnalite: function(a, b, c, d) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number' || typeof c !== 'number' || typeof d !== 'number') { |
|
|
throw new Error('nektales.verifierProportionnalite: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
if (b === 0 || d === 0) { |
|
|
throw new Error('nektales.verifierProportionnalite: Les dénominateurs ne peuvent pas être zéro.'); |
|
|
} |
|
|
return Math.abs((a / b) - (c / d)) < 1e-10; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekproba = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
probabiliteSimple: function(casFavorables, casPossibles) { |
|
|
if (typeof casFavorables !== 'number' || typeof casPossibles !== 'number' || |
|
|
!Number.isInteger(casFavorables) || !Number.isInteger(casPossibles) || |
|
|
casFavorables < 0 || casPossibles <= 0) { |
|
|
throw new Error('nekproba.probabiliteSimple: Les arguments doivent être des entiers positifs.'); |
|
|
} |
|
|
if (casFavorables > casPossibles) { |
|
|
throw new Error('nekproba.probabiliteSimple: Le nombre de cas favorables ne peut pas dépasser le nombre de cas possibles.'); |
|
|
} |
|
|
return casFavorables / casPossibles; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
probabiliteInverse: function(probabilite) { |
|
|
if (typeof probabilite !== 'number' || probabilite < 0 || probabilite > 1) { |
|
|
throw new Error('nekproba.probabiliteInverse: L\'argument doit être un nombre entre 0 et 1.'); |
|
|
} |
|
|
return 1 - probabilite; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
probabiliteUnion: function(probA, probB, probIntersection = 0) { |
|
|
if (typeof probA !== 'number' || typeof probB !== 'number' || typeof probIntersection !== 'number' || |
|
|
probA < 0 || probA > 1 || probB < 0 || probB > 1 || probIntersection < 0 || probIntersection > 1) { |
|
|
throw new Error('nekproba.probabiliteUnion: Les arguments doivent être des nombres entre 0 et 1.'); |
|
|
} |
|
|
return probA + probB - probIntersection; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekbel = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
message: function(message, style = 'info') { |
|
|
if (typeof message !== 'string') { |
|
|
throw new Error('nekbel.message: Le message doit être une chaîne de caractères.'); |
|
|
} |
|
|
const styles = { |
|
|
info: '💡 [INFO]', |
|
|
success: '✅ [SUCCÈS]', |
|
|
warning: '⚠️ [ATTENTION]', |
|
|
error: '❌ [ERREUR]' |
|
|
}; |
|
|
const prefix = styles[style] || styles.info; |
|
|
return `${prefix} ${message}`; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
executer: function(func, args = [], nom = 'fonction personnalisée') { |
|
|
if (typeof func !== 'function') { |
|
|
return this.message(`${nom} n'est pas une fonction valide.`, 'error'); |
|
|
} |
|
|
try { |
|
|
const resultat = func.apply(null, args); |
|
|
return { |
|
|
succes: true, |
|
|
resultat: resultat, |
|
|
message: this.message(`${nom} exécutée avec succès.`, 'success') |
|
|
}; |
|
|
} catch (error) { |
|
|
return { |
|
|
succes: false, |
|
|
erreur: error.message, |
|
|
message: this.message(`Erreur lors de l'exécution de ${nom}: ${error.message}`, 'error') |
|
|
}; |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekcreative = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
generateId: function(prefix = 'neko') { |
|
|
const timestamp = Date.now().toString(36); |
|
|
const random = Math.random().toString(36).substr(2, 5); |
|
|
return `${prefix}_${timestamp}_${random}`; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
chronometer: function(func, nom = 'fonction') { |
|
|
return function(...args) { |
|
|
const debut = performance.now(); |
|
|
const resultat = func.apply(this, args); |
|
|
const fin = performance.now(); |
|
|
console.log(`⏱️ ${nom} exécutée en ${(fin - debut).toFixed(2)}ms`); |
|
|
return resultat; |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memoize: function(func) { |
|
|
const cache = new Map(); |
|
|
return function(...args) { |
|
|
const key = JSON.stringify(args); |
|
|
if (cache.has(key)) { |
|
|
console.log('🎯 Résultat récupéré du cache'); |
|
|
return cache.get(key); |
|
|
} |
|
|
const resultat = func.apply(this, args); |
|
|
cache.set(key, resultat); |
|
|
return resultat; |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
couleurAleatoire: function(format = 'hex') { |
|
|
switch (format) { |
|
|
case 'hex': |
|
|
return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0'); |
|
|
case 'rgb': |
|
|
const r = Math.floor(Math.random() * 256); |
|
|
const g = Math.floor(Math.random() * 256); |
|
|
const b = Math.floor(Math.random() * 256); |
|
|
return `rgb(${r}, ${g}, ${b})`; |
|
|
case 'hsl': |
|
|
const h = Math.floor(Math.random() * 361); |
|
|
const s = Math.floor(Math.random() * 101); |
|
|
const l = Math.floor(Math.random() * 101); |
|
|
return `hsl(${h}, ${s}%, ${l}%)`; |
|
|
default: |
|
|
throw new Error('nekcreative.couleurAleatoire: Format non supporté. Utilisez "hex", "rgb" ou "hsl".'); |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekorror = { |
|
|
|
|
|
|
|
|
|
|
|
messagesPersonnalises: new Map(), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
definirMessage: function(codeErreur, message) { |
|
|
if (typeof codeErreur !== 'string' || typeof message !== 'string') { |
|
|
throw new Error('nekorror.definirMessage: Les arguments doivent être des chaînes de caractères.'); |
|
|
} |
|
|
this.messagesPersonnalises.set(codeErreur, message); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lancerErreur: function(codeErreur, donnees = null) { |
|
|
const messagePersonnalise = this.messagesPersonnalises.get(codeErreur); |
|
|
let message = messagePersonnalise || `Erreur inconnue: ${codeErreur}`; |
|
|
|
|
|
if (donnees) { |
|
|
message += ` | Données: ${JSON.stringify(donnees)}`; |
|
|
} |
|
|
|
|
|
const erreur = new Error(`🚨 [NEKOMATHS] ${message}`); |
|
|
erreur.code = codeErreur; |
|
|
erreur.donnees = donnees; |
|
|
throw erreur; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
executer: function(func, args = []) { |
|
|
try { |
|
|
const resultat = func.apply(null, args); |
|
|
return { |
|
|
succes: true, |
|
|
resultat: resultat, |
|
|
erreur: null |
|
|
}; |
|
|
} catch (error) { |
|
|
return { |
|
|
succes: false, |
|
|
resultat: null, |
|
|
erreur: { |
|
|
message: error.message, |
|
|
code: error.code || 'ERREUR_INCONNUE', |
|
|
donnees: error.donnees || null |
|
|
} |
|
|
}; |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log: function(niveau, message, donnees = null) { |
|
|
const timestamp = new Date().toISOString(); |
|
|
const niveaux = { |
|
|
debug: '🔍', |
|
|
info: 'ℹ️', |
|
|
warn: '⚠️', |
|
|
error: '💥' |
|
|
}; |
|
|
|
|
|
const emoji = niveaux[niveau] || 'ℹ️'; |
|
|
let logMessage = `${emoji} [${timestamp}] ${message}`; |
|
|
|
|
|
if (donnees) { |
|
|
logMessage += ` | ${JSON.stringify(donnees)}`; |
|
|
} |
|
|
|
|
|
console.log(logMessage); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekdraw = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rectangle: function(largeur, hauteur, caractere = '*') { |
|
|
if (typeof largeur !== 'number' || typeof hauteur !== 'number' || |
|
|
!Number.isInteger(largeur) || !Number.isInteger(hauteur) || |
|
|
largeur <= 0 || hauteur <= 0) { |
|
|
throw new Error('nekdraw.rectangle: Largeur et hauteur doivent être des entiers positifs.'); |
|
|
} |
|
|
let resultat = ''; |
|
|
for (let i = 0; i < hauteur; i++) { |
|
|
for (let j = 0; j < largeur; j++) { |
|
|
resultat += caractere; |
|
|
} |
|
|
resultat += '\n'; |
|
|
} |
|
|
return resultat; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
triangle: function(taille, caractere = '*') { |
|
|
if (typeof taille !== 'number' || !Number.isInteger(taille) || taille <= 0) { |
|
|
throw new Error('nekdraw.triangle: La taille doit être un entier positif.'); |
|
|
} |
|
|
let resultat = ''; |
|
|
for (let i = 1; i <= taille; i++) { |
|
|
resultat += ' '.repeat(taille - i) + caractere.repeat(2 * i - 1) + '\n'; |
|
|
} |
|
|
return resultat; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
afficher: function(dessin) { |
|
|
console.log(dessin); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function nekril(nombre, decimales = 2) { |
|
|
if (typeof nombre !== 'number' || typeof decimales !== 'number' || |
|
|
!Number.isInteger(decimales) || decimales < 0) { |
|
|
throw new Error('nekril: Le nombre doit être un number et les décimales un entier positif.'); |
|
|
} |
|
|
return Math.round(nombre * Math.pow(10, decimales)) / Math.pow(10, decimales); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekocust = { |
|
|
|
|
|
|
|
|
|
|
|
motsDictionnaire: { |
|
|
'zero': 0, 'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, |
|
|
'six': 6, 'seven': 7, 'eight': 8, 'nine': 9, 'ten': 10, |
|
|
'eleven': 11, 'twelve': 12, 'thirteen': 13, 'fourteen': 14, 'fifteen': 15, |
|
|
'sixteen': 16, 'seventeen': 17, 'eighteen': 18, 'nineteen': 19, 'twenty': 20, |
|
|
'thirty': 30, 'forty': 40, 'fifty': 50, 'sixty': 60, 'seventy': 70, |
|
|
'eighty': 80, 'ninety': 90, 'hundred': 100, 'thousand': 1000 |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
motEnNombre: function(mot) { |
|
|
if (typeof mot !== 'string') { |
|
|
throw new Error('nekocust.motEnNombre: L\'argument doit être une chaîne de caractères.'); |
|
|
} |
|
|
const motMinuscule = mot.toLowerCase(); |
|
|
if (this.motsDictionnaire.hasOwnProperty(motMinuscule)) { |
|
|
return this.motsDictionnaire[motMinuscule]; |
|
|
} |
|
|
throw new Error(`nekocust.motEnNombre: Mot "${mot}" non reconnu.`); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
additionMots: function(mot1, mot2) { |
|
|
const num1 = this.motEnNombre(mot1); |
|
|
const num2 = this.motEnNombre(mot2); |
|
|
return num1 + num2; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
soustractionMots: function(mot1, mot2) { |
|
|
const num1 = this.motEnNombre(mot1); |
|
|
const num2 = this.motEnNombre(mot2); |
|
|
return num1 - num2; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekrect = { |
|
|
|
|
|
|
|
|
|
|
|
objetsValeurs: { |
|
|
'rectangle': { largeur: 4, hauteur: 3, aire: function() { return this.largeur * this.hauteur; } }, |
|
|
'carre': { cote: 2, aire: function() { return this.cote * this.cote; } }, |
|
|
'poule': { oeufs: 12, valeur: function() { return this.oeufs; } }, |
|
|
'poire': { sucre: 8, valeur: function() { return this.sucre; } } |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
additionObjets: function(objet1, objet2, propriete = 'aire') { |
|
|
if (!this.objetsValeurs[objet1] || !this.objetsValeurs[objet2]) { |
|
|
throw new Error('nekrect.additionObjets: Objets non reconnus. Utilisez: rectangle, carre, poule, poire.'); |
|
|
} |
|
|
|
|
|
const obj1 = this.objetsValeurs[objet1]; |
|
|
const obj2 = this.objetsValeurs[objet2]; |
|
|
|
|
|
let valeur1, valeur2; |
|
|
|
|
|
if (propriete === 'aire' && obj1.aire) { |
|
|
valeur1 = obj1.aire(); |
|
|
} else if (propriete === 'valeur' && obj1.valeur) { |
|
|
valeur1 = obj1.valeur(); |
|
|
} else { |
|
|
throw new Error(`nekrect.additionObjets: Propriété "${propriete}" non disponible pour ${objet1}.`); |
|
|
} |
|
|
|
|
|
if (propriete === 'aire' && obj2.aire) { |
|
|
valeur2 = obj2.aire(); |
|
|
} else if (propriete === 'valeur' && obj2.valeur) { |
|
|
valeur2 = obj2.valeur(); |
|
|
} else { |
|
|
throw new Error(`nekrect.additionObjets: Propriété "${propriete}" non disponible pour ${objet2}.`); |
|
|
} |
|
|
|
|
|
return valeur1 + valeur2; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
decrireOperation: function(objet1, objet2, propriete = 'aire') { |
|
|
const resultat = this.additionObjets(objet1, objet2, propriete); |
|
|
return `Addition de ${objet1} + ${objet2} (${propriete}) = ${resultat}`; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekpap = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
volumePappus: function(aire, distanceCentroide) { |
|
|
if (typeof aire !== 'number' || typeof distanceCentroide !== 'number' || |
|
|
aire <= 0 || distanceCentroide <= 0) { |
|
|
throw new Error('nekpap.volumePappus: Les arguments doivent être des nombres positifs.'); |
|
|
} |
|
|
return 2 * Math.PI * aire * distanceCentroide; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
airePappus: function(longueur, distanceCentroide) { |
|
|
if (typeof longueur !== 'number' || typeof distanceCentroide !== 'number' || |
|
|
longueur <= 0 || distanceCentroide <= 0) { |
|
|
throw new Error('nekpap.airePappus: Les arguments doivent être des nombres positifs.'); |
|
|
} |
|
|
return 2 * Math.PI * longueur * distanceCentroide; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
centroideVolume: function(volume, aire) { |
|
|
if (typeof volume !== 'number' || typeof aire !== 'number' || |
|
|
volume <= 0 || aire <= 0) { |
|
|
throw new Error('nekpap.centroideVolume: Les arguments doivent être des nombres positifs.'); |
|
|
} |
|
|
return volume / (2 * Math.PI * aire); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekdesar = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pointsAlignes: function(point1, point2, point3) { |
|
|
if (!this.validerPoint(point1) || !this.validerPoint(point2) || !this.validerPoint(point3)) { |
|
|
throw new Error('nekdesar.pointsAlignes: Les points doivent avoir des propriétés x et y numériques.'); |
|
|
} |
|
|
|
|
|
|
|
|
const determinant = (point2.x - point1.x) * (point3.y - point1.y) - |
|
|
(point3.x - point1.x) * (point2.y - point1.y); |
|
|
|
|
|
return Math.abs(determinant) < 1e-10; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
intersectionDroites: function(p1, p2, p3, p4) { |
|
|
if (!this.validerPoint(p1) || !this.validerPoint(p2) || !this.validerPoint(p3) || !this.validerPoint(p4)) { |
|
|
throw new Error('nekdesar.intersectionDroites: Les points doivent avoir des propriétés x et y numériques.'); |
|
|
} |
|
|
|
|
|
const denom = (p1.x - p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x - p4.x); |
|
|
|
|
|
if (Math.abs(denom) < 1e-10) { |
|
|
return null; |
|
|
} |
|
|
|
|
|
const t = ((p1.x - p3.x) * (p3.y - p4.y) - (p1.y - p3.y) * (p3.x - p4.x)) / denom; |
|
|
|
|
|
return { |
|
|
x: p1.x + t * (p2.x - p1.x), |
|
|
y: p1.y + t * (p2.y - p1.y) |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
verifierDesargues: function(triangle1, triangle2) { |
|
|
if (!Array.isArray(triangle1) || !Array.isArray(triangle2) || |
|
|
triangle1.length !== 3 || triangle2.length !== 3) { |
|
|
throw new Error('nekdesar.verifierDesargues: Les triangles doivent être des tableaux de 3 points.'); |
|
|
} |
|
|
|
|
|
|
|
|
for (let point of [...triangle1, ...triangle2]) { |
|
|
if (!this.validerPoint(point)) { |
|
|
throw new Error('nekdesar.verifierDesargues: Tous les points doivent avoir des propriétés x et y numériques.'); |
|
|
} |
|
|
} |
|
|
|
|
|
return { |
|
|
triangles: 'valides', |
|
|
message: 'Configuration de Desargues détectée - triangles en perspective', |
|
|
triangle1: triangle1, |
|
|
triangle2: triangle2 |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
validerPoint: function(point) { |
|
|
return point && typeof point.x === 'number' && typeof point.y === 'number'; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekident = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resoudreLineaire: function(a, b, resultat) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number' || typeof resultat !== 'number') { |
|
|
throw new Error('nekident.resoudreLineaire: Tous les arguments doivent être des nombres.'); |
|
|
} |
|
|
if (a === 0) { |
|
|
throw new Error('nekident.resoudreLineaire: Le coefficient de x ne peut pas être zéro.'); |
|
|
} |
|
|
return (resultat - b) / a; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
verifierSolution: function(x, operation, operande, resultatAttendu) { |
|
|
let resultat; |
|
|
switch (operation) { |
|
|
case 'add': |
|
|
resultat = x + operande; |
|
|
break; |
|
|
case 'sub': |
|
|
resultat = x - operande; |
|
|
break; |
|
|
case 'mult': |
|
|
resultat = x * operande; |
|
|
break; |
|
|
case 'div': |
|
|
if (operande === 0) throw new Error('Division par zéro impossible.'); |
|
|
resultat = x / operande; |
|
|
break; |
|
|
default: |
|
|
throw new Error('nekident.verifierSolution: Opération non supportée.'); |
|
|
} |
|
|
return Math.abs(resultat - resultatAttendu) < 1e-10; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trouverX: function(operation, operande, resultatAttendu) { |
|
|
switch (operation) { |
|
|
case 'add': |
|
|
return resultatAttendu - operande; |
|
|
case 'sub': |
|
|
return resultatAttendu + operande; |
|
|
case 'mult': |
|
|
if (operande === 0) throw new Error('Impossible de diviser par zéro.'); |
|
|
return resultatAttendu / operande; |
|
|
case 'div': |
|
|
return resultatAttendu * operande; |
|
|
default: |
|
|
throw new Error('nekident.trouverX: Opération non supportée.'); |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekaqua = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
quadratique: function(a, b, c) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number' || typeof c !== 'number') { |
|
|
throw new Error('nekaqua.quadratique: Tous les arguments doivent être des nombres.'); |
|
|
} |
|
|
if (a === 0) { |
|
|
throw new Error('nekaqua.quadratique: Le coefficient de x² ne peut pas être zéro.'); |
|
|
} |
|
|
|
|
|
const discriminant = b * b - 4 * a * c; |
|
|
|
|
|
if (discriminant > 0) { |
|
|
const x1 = (-b + Math.sqrt(discriminant)) / (2 * a); |
|
|
const x2 = (-b - Math.sqrt(discriminant)) / (2 * a); |
|
|
return { type: 'deux_solutions', x1: x1, x2: x2, discriminant: discriminant }; |
|
|
} else if (discriminant === 0) { |
|
|
const x = -b / (2 * a); |
|
|
return { type: 'une_solution', x: x, discriminant: discriminant }; |
|
|
} else { |
|
|
return { type: 'aucune_solution_reelle', discriminant: discriminant }; |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
systeme2x2: function(a1, b1, c1, a2, b2, c2) { |
|
|
const determinant = a1 * b2 - a2 * b1; |
|
|
|
|
|
if (Math.abs(determinant) < 1e-10) { |
|
|
return { type: 'aucune_solution_unique', message: 'Système indéterminé ou incompatible' }; |
|
|
} |
|
|
|
|
|
const x = (c1 * b2 - c2 * b1) / determinant; |
|
|
const y = (a1 * c2 - a2 * c1) / determinant; |
|
|
|
|
|
return { type: 'solution_unique', x: x, y: y }; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
evaluerPolynome: function(coefficients, x) { |
|
|
if (!Array.isArray(coefficients) || coefficients.some(c => typeof c !== 'number')) { |
|
|
throw new Error('nekaqua.evaluerPolynome: Les coefficients doivent être un tableau de nombres.'); |
|
|
} |
|
|
let resultat = 0; |
|
|
for (let i = 0; i < coefficients.length; i++) { |
|
|
resultat += coefficients[i] * Math.pow(x, coefficients.length - 1 - i); |
|
|
} |
|
|
return resultat; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekfrac = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
simplifier: function(numerateur, denominateur) { |
|
|
if (typeof numerateur !== 'number' || typeof denominateur !== 'number' || |
|
|
!Number.isInteger(numerateur) || !Number.isInteger(denominateur)) { |
|
|
throw new Error('nekfrac.simplifier: Les arguments doivent être des entiers.'); |
|
|
} |
|
|
if (denominateur === 0) { |
|
|
throw new Error('nekfrac.simplifier: Le dénominateur ne peut pas être zéro.'); |
|
|
} |
|
|
|
|
|
const pgcd = this.pgcd(Math.abs(numerateur), Math.abs(denominateur)); |
|
|
return { |
|
|
numerateur: numerateur / pgcd, |
|
|
denominateur: denominateur / pgcd, |
|
|
decimal: (numerateur / pgcd) / (denominateur / pgcd) |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
additionner: function(num1, den1, num2, den2) { |
|
|
const nouveauNum = num1 * den2 + num2 * den1; |
|
|
const nouveauDen = den1 * den2; |
|
|
return this.simplifier(nouveauNum, nouveauDen); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
multiplier: function(num1, den1, num2, den2) { |
|
|
const nouveauNum = num1 * num2; |
|
|
const nouveauDen = den1 * den2; |
|
|
return this.simplifier(nouveauNum, nouveauDen); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pgcd: function(a, b) { |
|
|
while (b !== 0) { |
|
|
const temp = b; |
|
|
b = a % b; |
|
|
a = temp; |
|
|
} |
|
|
return a; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nektin = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resoudreCarree: function(a, b) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number') { |
|
|
throw new Error('nektin.resoudreCarree: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
if (a === 0) { |
|
|
throw new Error('nektin.resoudreCarree: Le coefficient ne peut pas être zéro.'); |
|
|
} |
|
|
|
|
|
const valeur = b / a; |
|
|
if (valeur < 0) { |
|
|
return { type: 'aucune_solution_reelle', message: 'Racine carrée d\'un nombre négatif' }; |
|
|
} else if (valeur === 0) { |
|
|
return { type: 'une_solution', x: 0 }; |
|
|
} else { |
|
|
const racine = Math.sqrt(valeur); |
|
|
return { type: 'deux_solutions', x1: racine, x2: -racine }; |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resoudreCube: function(a, b) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number') { |
|
|
throw new Error('nektin.resoudreCube: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
if (a === 0) { |
|
|
throw new Error('nektin.resoudreCube: Le coefficient ne peut pas être zéro.'); |
|
|
} |
|
|
|
|
|
const valeur = b / a; |
|
|
const racine = Math.cbrt(valeur); |
|
|
return { type: 'une_solution', x: racine }; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fractionPuissance: function(num, den, exposant) { |
|
|
if (typeof num !== 'number' || typeof den !== 'number' || typeof exposant !== 'number') { |
|
|
throw new Error('nektin.fractionPuissance: Tous les arguments doivent être des nombres.'); |
|
|
} |
|
|
if (den === 0) { |
|
|
throw new Error('nektin.fractionPuissance: Le dénominateur ne peut pas être zéro.'); |
|
|
} |
|
|
|
|
|
const nouveauNum = Math.pow(num, exposant); |
|
|
const nouveauDen = Math.pow(den, exposant); |
|
|
|
|
|
return { |
|
|
numerateur: nouveauNum, |
|
|
denominateur: nouveauDen, |
|
|
decimal: nouveauNum / nouveauDen, |
|
|
exposant: exposant |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekalpha = { |
|
|
|
|
|
|
|
|
|
|
|
valeur: 2.5029078750958928, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serie: function(n) { |
|
|
if (typeof n !== 'number' || !Number.isInteger(n) || n <= 0) { |
|
|
throw new Error('nekalpha.serie: n doit être un entier positif.'); |
|
|
} |
|
|
let somme = 0; |
|
|
for (let i = 1; i <= n; i++) { |
|
|
somme += this.valeur / Math.pow(i, 2); |
|
|
} |
|
|
return somme; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
transformation: function(x) { |
|
|
if (typeof x !== 'number') { |
|
|
throw new Error('nekalpha.transformation: L\'argument doit être un nombre.'); |
|
|
} |
|
|
return this.valeur * x * (1 - x); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekbeta = { |
|
|
|
|
|
|
|
|
|
|
|
valeur: 1.5707963267948966, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fonction: function(a, b) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number' || a <= 0 || b <= 0) { |
|
|
throw new Error('nekbeta.fonction: Les paramètres doivent être des nombres positifs.'); |
|
|
} |
|
|
|
|
|
return (this.gamma(a) * this.gamma(b)) / this.gamma(a + b); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gamma: function(x) { |
|
|
if (x <= 0) return Infinity; |
|
|
if (x === 1) return 1; |
|
|
if (x === 2) return 1; |
|
|
|
|
|
return Math.sqrt(2 * Math.PI / x) * Math.pow(x / Math.E, x); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
distribution: function(x, alpha, beta) { |
|
|
if (x < 0 || x > 1) { |
|
|
throw new Error('nekbeta.distribution: x doit être entre 0 et 1.'); |
|
|
} |
|
|
return Math.pow(x, alpha - 1) * Math.pow(1 - x, beta - 1); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekomega = { |
|
|
|
|
|
|
|
|
|
|
|
valeur: 0.6180339887498948, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spirale: function(t) { |
|
|
if (typeof t !== 'number') { |
|
|
throw new Error('nekomega.spirale: Le paramètre doit être un nombre.'); |
|
|
} |
|
|
const r = Math.exp(this.valeur * t); |
|
|
const theta = t; |
|
|
return { |
|
|
r: r, |
|
|
theta: theta, |
|
|
x: r * Math.cos(theta), |
|
|
y: r * Math.sin(theta) |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fibonacciOmega: function(n) { |
|
|
if (typeof n !== 'number' || !Number.isInteger(n) || n < 0) { |
|
|
throw new Error('nekomega.fibonacciOmega: n doit être un entier non négatif.'); |
|
|
} |
|
|
const phi = (1 + Math.sqrt(5)) / 2; |
|
|
return Math.round((Math.pow(phi, n) - Math.pow(-this.valeur, n)) / Math.sqrt(5)); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
convergence: function(iterations) { |
|
|
if (typeof iterations !== 'number' || !Number.isInteger(iterations) || iterations <= 0) { |
|
|
throw new Error('nekomega.convergence: iterations doit être un entier positif.'); |
|
|
} |
|
|
let valeur = 1; |
|
|
for (let i = 0; i < iterations; i++) { |
|
|
valeur = Math.exp(-valeur); |
|
|
} |
|
|
return valeur; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekcopare = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
comparer: function(a, b) { |
|
|
if (typeof a !== 'number' || typeof b !== 'number') { |
|
|
throw new Error('nekcopare.comparer: Les arguments doivent être des nombres.'); |
|
|
} |
|
|
|
|
|
let relation; |
|
|
let symbole; |
|
|
|
|
|
if (a > b) { |
|
|
relation = 'plus_grand'; |
|
|
symbole = '>'; |
|
|
} else if (a < b) { |
|
|
relation = 'plus_petit'; |
|
|
symbole = '<'; |
|
|
} else { |
|
|
relation = 'egal'; |
|
|
symbole = '='; |
|
|
} |
|
|
|
|
|
return { |
|
|
a: a, |
|
|
b: b, |
|
|
relation: relation, |
|
|
symbole: symbole, |
|
|
message: `${a} ${symbole} ${b}`, |
|
|
difference: Math.abs(a - b) |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maximum: function(nombres) { |
|
|
if (!Array.isArray(nombres) || nombres.length === 0) { |
|
|
throw new Error('nekcopare.maximum: L\'argument doit être un tableau non vide.'); |
|
|
} |
|
|
if (nombres.some(n => typeof n !== 'number')) { |
|
|
throw new Error('nekcopare.maximum: Tous les éléments doivent être des nombres.'); |
|
|
} |
|
|
|
|
|
const max = Math.max(...nombres); |
|
|
const index = nombres.indexOf(max); |
|
|
|
|
|
return { |
|
|
valeur: max, |
|
|
index: index, |
|
|
tableau: nombres |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
minimum: function(nombres) { |
|
|
if (!Array.isArray(nombres) || nombres.length === 0) { |
|
|
throw new Error('nekcopare.minimum: L\'argument doit être un tableau non vide.'); |
|
|
} |
|
|
if (nombres.some(n => typeof n !== 'number')) { |
|
|
throw new Error('nekcopare.minimum: Tous les éléments doivent être des nombres.'); |
|
|
} |
|
|
|
|
|
const min = Math.min(...nombres); |
|
|
const index = nombres.indexOf(min); |
|
|
|
|
|
return { |
|
|
valeur: min, |
|
|
index: index, |
|
|
tableau: nombres |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekdone = { |
|
|
|
|
|
|
|
|
|
|
|
bases: new Map(), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
creerBase: function(nom, structure = []) { |
|
|
if (typeof nom !== 'string') { |
|
|
throw new Error('nekdone.creerBase: Le nom doit être une chaîne de caractères.'); |
|
|
} |
|
|
|
|
|
const base = { |
|
|
nom: nom, |
|
|
structure: structure, |
|
|
donnees: [], |
|
|
creeLe: new Date(), |
|
|
operations: [] |
|
|
}; |
|
|
|
|
|
this.bases.set(nom, base); |
|
|
return base; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ajouterDonnee: function(nomBase, donnee) { |
|
|
const base = this.bases.get(nomBase); |
|
|
if (!base) { |
|
|
throw new Error('nekdone.ajouterDonnee: Base de données non trouvée.'); |
|
|
} |
|
|
|
|
|
base.donnees.push({ |
|
|
id: base.donnees.length + 1, |
|
|
donnee: donnee, |
|
|
ajouteLe: new Date() |
|
|
}); |
|
|
|
|
|
base.operations.push({ |
|
|
type: 'ajout', |
|
|
timestamp: new Date(), |
|
|
donnee: donnee |
|
|
}); |
|
|
|
|
|
return true; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculer: function(nomBase, propriete, operation) { |
|
|
const base = this.bases.get(nomBase); |
|
|
if (!base) { |
|
|
throw new Error('nekdone.calculer: Base de données non trouvée.'); |
|
|
} |
|
|
|
|
|
const valeurs = base.donnees |
|
|
.map(item => item.donnee[propriete]) |
|
|
.filter(val => typeof val === 'number'); |
|
|
|
|
|
if (valeurs.length === 0) { |
|
|
throw new Error('nekdone.calculer: Aucune valeur numérique trouvée pour cette propriété.'); |
|
|
} |
|
|
|
|
|
switch (operation) { |
|
|
case 'somme': |
|
|
return valeurs.reduce((acc, val) => acc + val, 0); |
|
|
case 'moyenne': |
|
|
return valeurs.reduce((acc, val) => acc + val, 0) / valeurs.length; |
|
|
case 'max': |
|
|
return Math.max(...valeurs); |
|
|
case 'min': |
|
|
return Math.min(...valeurs); |
|
|
default: |
|
|
throw new Error('nekdone.calculer: Opération non supportée.'); |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
obtenirBase: function(nomBase) { |
|
|
const base = this.bases.get(nomBase); |
|
|
if (!base) { |
|
|
throw new Error('nekdone.obtenirBase: Base de données non trouvée.'); |
|
|
} |
|
|
return base; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekarin = { |
|
|
|
|
|
|
|
|
|
|
|
fonctions: new Map(), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enregistrerFonction: function(nom, fonction, description = '') { |
|
|
if (typeof nom !== 'string' || typeof fonction !== 'function') { |
|
|
throw new Error('nekarin.enregistrerFonction: Nom invalide ou fonction non valide.'); |
|
|
} |
|
|
|
|
|
this.fonctions.set(nom, { |
|
|
fonction: fonction, |
|
|
description: description, |
|
|
nom: nom, |
|
|
creeLe: new Date() |
|
|
}); |
|
|
|
|
|
return true; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
executer: function(nom, ...args) { |
|
|
const fonctionInfo = this.fonctions.get(nom); |
|
|
if (!fonctionInfo) { |
|
|
throw new Error('nekarin.executer: Fonction non trouvée.'); |
|
|
} |
|
|
|
|
|
try { |
|
|
return fonctionInfo.fonction.apply(null, args); |
|
|
} catch (error) { |
|
|
throw new Error(`nekarin.executer: Erreur lors de l'exécution de ${nom}: ${error.message}`); |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
combiner: function(nom1, nom2, operation, ...args) { |
|
|
const resultat1 = this.executer(nom1, ...args); |
|
|
const resultat2 = this.executer(nom2, ...args); |
|
|
|
|
|
if (typeof resultat1 !== 'number' || typeof resultat2 !== 'number') { |
|
|
throw new Error('nekarin.combiner: Les fonctions doivent retourner des nombres.'); |
|
|
} |
|
|
|
|
|
switch (operation) { |
|
|
case 'add': |
|
|
return resultat1 + resultat2; |
|
|
case 'sub': |
|
|
return resultat1 - resultat2; |
|
|
case 'mult': |
|
|
return resultat1 * resultat2; |
|
|
case 'div': |
|
|
if (resultat2 === 0) throw new Error('Division par zéro.'); |
|
|
return resultat1 / resultat2; |
|
|
default: |
|
|
throw new Error('nekarin.combiner: Opération non supportée.'); |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
listerFonctions: function() { |
|
|
return Array.from(this.fonctions.entries()).map(([nom, info]) => ({ |
|
|
nom: nom, |
|
|
description: info.description, |
|
|
creeLe: info.creeLe |
|
|
})); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekgrap = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
genererPoints: function(func, xMin = -10, xMax = 10, pas = 0.1) { |
|
|
if (typeof func !== 'function') { |
|
|
throw new Error('nekgrap.genererPoints: Le premier argument doit être une fonction.'); |
|
|
} |
|
|
const points = []; |
|
|
for (let x = xMin; x <= xMax; x += pas) { |
|
|
try { |
|
|
const y = func(x); |
|
|
if (typeof y === 'number' && !isNaN(y) && isFinite(y)) { |
|
|
points.push({ x: x, y: y }); |
|
|
} |
|
|
} catch (error) { |
|
|
|
|
|
} |
|
|
} |
|
|
return points; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
afficherConsole: function(points, largeur = 80, hauteur = 20) { |
|
|
if (!Array.isArray(points) || points.length === 0) { |
|
|
throw new Error('nekgrap.afficherConsole: Points invalides.'); |
|
|
} |
|
|
|
|
|
const xValues = points.map(p => p.x); |
|
|
const yValues = points.map(p => p.y); |
|
|
const xMin = Math.min(...xValues); |
|
|
const xMax = Math.max(...xValues); |
|
|
const yMin = Math.min(...yValues); |
|
|
const yMax = Math.max(...yValues); |
|
|
|
|
|
let graphique = ''; |
|
|
for (let row = 0; row < hauteur; row++) { |
|
|
let ligne = ''; |
|
|
for (let col = 0; col < largeur; col++) { |
|
|
const x = xMin + (col / (largeur - 1)) * (xMax - xMin); |
|
|
const y = yMax - (row / (hauteur - 1)) * (yMax - yMin); |
|
|
|
|
|
|
|
|
const pointProche = points.reduce((prev, curr) => { |
|
|
const distPrev = Math.abs(prev.x - x) + Math.abs(prev.y - y); |
|
|
const distCurr = Math.abs(curr.x - x) + Math.abs(curr.y - y); |
|
|
return distCurr < distPrev ? curr : prev; |
|
|
}); |
|
|
|
|
|
if (Math.abs(pointProche.x - x) < (xMax - xMin) / largeur && |
|
|
Math.abs(pointProche.y - y) < (yMax - yMin) / hauteur) { |
|
|
ligne += '*'; |
|
|
} else if (Math.abs(y) < (yMax - yMin) / hauteur) { |
|
|
ligne += '-'; |
|
|
} else if (Math.abs(x) < (xMax - xMin) / largeur) { |
|
|
ligne += '|'; |
|
|
} else { |
|
|
ligne += ' '; |
|
|
} |
|
|
} |
|
|
graphique += ligne + '\n'; |
|
|
} |
|
|
return graphique; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tracer: function(func, options = {}) { |
|
|
const opts = { |
|
|
xMin: -10, |
|
|
xMax: 10, |
|
|
pas: 0.1, |
|
|
largeur: 80, |
|
|
hauteur: 20, |
|
|
...options |
|
|
}; |
|
|
|
|
|
const points = this.genererPoints(func, opts.xMin, opts.xMax, opts.pas); |
|
|
const graphique = this.afficherConsole(points, opts.largeur, opts.hauteur); |
|
|
console.log(graphique); |
|
|
return points; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekoser = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
arithmetique: function(premier, raison, n) { |
|
|
if (typeof premier !== 'number' || typeof raison !== 'number' || |
|
|
typeof n !== 'number' || !Number.isInteger(n) || n <= 0) { |
|
|
throw new Error('nekoser.arithmetique: Arguments invalides.'); |
|
|
} |
|
|
|
|
|
const termes = []; |
|
|
for (let i = 0; i < n; i++) { |
|
|
termes.push(premier + i * raison); |
|
|
} |
|
|
|
|
|
return { |
|
|
termes: termes, |
|
|
somme: n * (2 * premier + (n - 1) * raison) / 2, |
|
|
type: 'arithmetique', |
|
|
premier: premier, |
|
|
raison: raison, |
|
|
nombreTermes: n |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
geometrique: function(premier, raison, n) { |
|
|
if (typeof premier !== 'number' || typeof raison !== 'number' || |
|
|
typeof n !== 'number' || !Number.isInteger(n) || n <= 0) { |
|
|
throw new Error('nekoser.geometrique: Arguments invalides.'); |
|
|
} |
|
|
|
|
|
const termes = []; |
|
|
for (let i = 0; i < n; i++) { |
|
|
termes.push(premier * Math.pow(raison, i)); |
|
|
} |
|
|
|
|
|
let somme; |
|
|
if (raison === 1) { |
|
|
somme = n * premier; |
|
|
} else { |
|
|
somme = premier * (1 - Math.pow(raison, n)) / (1 - raison); |
|
|
} |
|
|
|
|
|
return { |
|
|
termes: termes, |
|
|
somme: somme, |
|
|
type: 'geometrique', |
|
|
premier: premier, |
|
|
raison: raison, |
|
|
nombreTermes: n |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const neka = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serieGeometriqueInfinie: function(premier, raison) { |
|
|
if (typeof premier !== 'number' || typeof raison !== 'number') { |
|
|
throw new Error('neka.serieGeometriqueInfinie: Arguments invalides.'); |
|
|
} |
|
|
if (Math.abs(raison) >= 1) { |
|
|
throw new Error('neka.serieGeometriqueInfinie: |raison| doit être < 1 pour la convergence.'); |
|
|
} |
|
|
|
|
|
return premier / (1 - raison); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
approximerSerie: function(termFunction, maxTermes = 1000, precision = 1e-10) { |
|
|
if (typeof termFunction !== 'function') { |
|
|
throw new Error('neka.approximerSerie: Le premier argument doit être une fonction.'); |
|
|
} |
|
|
|
|
|
let somme = 0; |
|
|
let termePrecedent = 0; |
|
|
|
|
|
for (let n = 1; n <= maxTermes; n++) { |
|
|
const terme = termFunction(n); |
|
|
somme += terme; |
|
|
|
|
|
if (Math.abs(terme - termePrecedent) < precision) { |
|
|
return { |
|
|
somme: somme, |
|
|
nombreTermes: n, |
|
|
converge: true, |
|
|
precision: Math.abs(terme - termePrecedent) |
|
|
}; |
|
|
} |
|
|
termePrecedent = terme; |
|
|
} |
|
|
|
|
|
return { |
|
|
somme: somme, |
|
|
nombreTermes: maxTermes, |
|
|
converge: false, |
|
|
precision: Math.abs(termFunction(maxTermes)) |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekoma = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
creer: function(donnees) { |
|
|
if (!Array.isArray(donnees) || donnees.length === 0) { |
|
|
throw new Error('nekoma.creer: Données invalides.'); |
|
|
} |
|
|
|
|
|
const lignes = donnees.length; |
|
|
const colonnes = donnees[0].length; |
|
|
|
|
|
|
|
|
for (let ligne of donnees) { |
|
|
if (!Array.isArray(ligne) || ligne.length !== colonnes) { |
|
|
throw new Error('nekoma.creer: Toutes les lignes doivent avoir la même longueur.'); |
|
|
} |
|
|
} |
|
|
|
|
|
return { |
|
|
donnees: donnees, |
|
|
lignes: lignes, |
|
|
colonnes: colonnes, |
|
|
type: 'matrice' |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inverser2x2: function(matrice) { |
|
|
if (!matrice || matrice.lignes !== 2 || matrice.colonnes !== 2) { |
|
|
throw new Error('nekoma.inverser2x2: Matrice 2x2 requise.'); |
|
|
} |
|
|
|
|
|
const [[a, b], [c, d]] = matrice.donnees; |
|
|
const det = a * d - b * c; |
|
|
|
|
|
if (Math.abs(det) < 1e-10) { |
|
|
throw new Error('nekoma.inverser2x2: Matrice non inversible (déterminant = 0).'); |
|
|
} |
|
|
|
|
|
const inverse = [ |
|
|
[d / det, -b / det], |
|
|
[-c / det, a / det] |
|
|
]; |
|
|
|
|
|
return this.creer(inverse); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
multiplier: function(matrice1, matrice2) { |
|
|
if (matrice1.colonnes !== matrice2.lignes) { |
|
|
throw new Error('nekoma.multiplier: Dimensions incompatibles.'); |
|
|
} |
|
|
|
|
|
const resultat = []; |
|
|
for (let i = 0; i < matrice1.lignes; i++) { |
|
|
resultat[i] = []; |
|
|
for (let j = 0; j < matrice2.colonnes; j++) { |
|
|
let somme = 0; |
|
|
for (let k = 0; k < matrice1.colonnes; k++) { |
|
|
somme += matrice1.donnees[i][k] * matrice2.donnees[k][j]; |
|
|
} |
|
|
resultat[i][j] = somme; |
|
|
} |
|
|
} |
|
|
|
|
|
return this.creer(resultat); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekyu = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
determinant2x2: function(matrice) { |
|
|
if (!matrice || matrice.lignes !== 2 || matrice.colonnes !== 2) { |
|
|
throw new Error('nekyu.determinant2x2: Matrice 2x2 requise.'); |
|
|
} |
|
|
|
|
|
const [[a, b], [c, d]] = matrice.donnees; |
|
|
return a * d - b * c; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
determinant3x3: function(matrice) { |
|
|
if (!matrice || matrice.lignes !== 3 || matrice.colonnes !== 3) { |
|
|
throw new Error('nekyu.determinant3x3: Matrice 3x3 requise.'); |
|
|
} |
|
|
|
|
|
const m = matrice.donnees; |
|
|
return m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) - |
|
|
m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + |
|
|
m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
identite: function(taille) { |
|
|
if (typeof taille !== 'number' || !Number.isInteger(taille) || taille <= 0) { |
|
|
throw new Error('nekyu.identite: Taille invalide.'); |
|
|
} |
|
|
|
|
|
const matrice = []; |
|
|
for (let i = 0; i < taille; i++) { |
|
|
matrice[i] = []; |
|
|
for (let j = 0; j < taille; j++) { |
|
|
matrice[i][j] = (i === j) ? 1 : 0; |
|
|
} |
|
|
} |
|
|
|
|
|
return nekoma.creer(matrice); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekonew = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trouverRacine: function(func, derivee, x0, tolerance = 1e-10, maxIterations = 100) { |
|
|
if (typeof func !== 'function' || typeof derivee !== 'function') { |
|
|
throw new Error('nekonew.trouverRacine: Les deux premiers arguments doivent être des fonctions.'); |
|
|
} |
|
|
|
|
|
let x = x0; |
|
|
const iterations = []; |
|
|
|
|
|
for (let i = 0; i < maxIterations; i++) { |
|
|
const fx = func(x); |
|
|
const fpx = derivee(x); |
|
|
|
|
|
if (Math.abs(fpx) < 1e-15) { |
|
|
throw new Error('nekonew.trouverRacine: Dérivée trop proche de zéro.'); |
|
|
} |
|
|
|
|
|
const nouveauX = x - fx / fpx; |
|
|
|
|
|
iterations.push({ |
|
|
iteration: i + 1, |
|
|
x: x, |
|
|
fx: fx, |
|
|
fpx: fpx, |
|
|
nouveauX: nouveauX |
|
|
}); |
|
|
|
|
|
if (Math.abs(nouveauX - x) < tolerance) { |
|
|
return { |
|
|
racine: nouveauX, |
|
|
iterations: iterations, |
|
|
converge: true, |
|
|
precision: Math.abs(nouveauX - x) |
|
|
}; |
|
|
} |
|
|
|
|
|
x = nouveauX; |
|
|
} |
|
|
|
|
|
return { |
|
|
racine: x, |
|
|
iterations: iterations, |
|
|
converge: false, |
|
|
precision: Math.abs(func(x)) |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekcarlo = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
estimerPi: function(nombrePoints = 1000000) { |
|
|
let pointsDansCercle = 0; |
|
|
|
|
|
for (let i = 0; i < nombrePoints; i++) { |
|
|
const x = Math.random() * 2 - 1; |
|
|
const y = Math.random() * 2 - 1; |
|
|
|
|
|
if (x * x + y * y <= 1) { |
|
|
pointsDansCercle++; |
|
|
} |
|
|
} |
|
|
|
|
|
const estimation = 4 * pointsDansCercle / nombrePoints; |
|
|
|
|
|
return { |
|
|
estimation: estimation, |
|
|
erreur: Math.abs(estimation - Math.PI), |
|
|
nombrePoints: nombrePoints, |
|
|
pointsDansCercle: pointsDansCercle |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
integrer: function(func, a, b, nombrePoints = 100000) { |
|
|
if (typeof func !== 'function') { |
|
|
throw new Error('nekcarlo.integrer: Premier argument doit être une fonction.'); |
|
|
} |
|
|
|
|
|
let somme = 0; |
|
|
|
|
|
for (let i = 0; i < nombrePoints; i++) { |
|
|
const x = a + Math.random() * (b - a); |
|
|
somme += func(x); |
|
|
} |
|
|
|
|
|
const estimation = (b - a) * somme / nombrePoints; |
|
|
|
|
|
return { |
|
|
estimation: estimation, |
|
|
intervalle: [a, b], |
|
|
nombrePoints: nombrePoints |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekinterac = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
creerMenu: function(options) { |
|
|
const titre = options.titre || 'Menu Nekomaths'; |
|
|
const choix = options.choix || []; |
|
|
|
|
|
let menu = `\n=== ${titre} ===\n`; |
|
|
|
|
|
choix.forEach((choice, index) => { |
|
|
menu += `${index + 1}. ${choice.nom}\n`; |
|
|
}); |
|
|
|
|
|
menu += '0. Quitter\n'; |
|
|
menu += 'Votre choix: '; |
|
|
|
|
|
return menu; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculateur: function(operation = 'addition') { |
|
|
const operations = { |
|
|
addition: { symbole: '+', nom: 'Addition' }, |
|
|
soustraction: { symbole: '-', nom: 'Soustraction' }, |
|
|
multiplication: { symbole: '*', nom: 'Multiplication' }, |
|
|
division: { symbole: '/', nom: 'Division' } |
|
|
}; |
|
|
|
|
|
const op = operations[operation]; |
|
|
if (!op) { |
|
|
throw new Error('nekinterac.calculateur: Opération non supportée.'); |
|
|
} |
|
|
|
|
|
return `\n=== Calculateur ${op.nom} ===\n` + |
|
|
`Entrez deux nombres pour effectuer: a ${op.symbole} b\n` + |
|
|
`Tapez 'menu' pour revenir au menu principal\n`; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekconvert = { |
|
|
|
|
|
|
|
|
|
|
|
conversions: { |
|
|
longueur: { |
|
|
metre: 1, |
|
|
kilometre: 0.001, |
|
|
centimetre: 100, |
|
|
millimetre: 1000, |
|
|
pouce: 39.3701, |
|
|
pied: 3.28084, |
|
|
yard: 1.09361, |
|
|
mile: 0.000621371 |
|
|
}, |
|
|
poids: { |
|
|
kilogramme: 1, |
|
|
gramme: 1000, |
|
|
tonne: 0.001, |
|
|
livre: 2.20462, |
|
|
once: 35.274 |
|
|
}, |
|
|
temperature: { |
|
|
celsius: { offset: 0, factor: 1 }, |
|
|
fahrenheit: { offset: 32, factor: 9/5 }, |
|
|
kelvin: { offset: 273.15, factor: 1 } |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
convertir: function(valeur, uniteSource, uniteCible, type = 'longueur') { |
|
|
if (typeof valeur !== 'number') { |
|
|
throw new Error('nekconvert.convertir: La valeur doit être un nombre.'); |
|
|
} |
|
|
|
|
|
const table = this.conversions[type]; |
|
|
if (!table) { |
|
|
throw new Error('nekconvert.convertir: Type de conversion non supporté.'); |
|
|
} |
|
|
|
|
|
if (type === 'temperature') { |
|
|
return this.convertirTemperature(valeur, uniteSource, uniteCible); |
|
|
} |
|
|
|
|
|
const facteurSource = table[uniteSource]; |
|
|
const facteurCible = table[uniteCible]; |
|
|
|
|
|
if (!facteurSource || !facteurCible) { |
|
|
throw new Error('nekconvert.convertir: Unité non supportée.'); |
|
|
} |
|
|
|
|
|
|
|
|
const valeurBase = valeur / facteurSource; |
|
|
return valeurBase * facteurCible; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
convertirTemperature: function(valeur, uniteSource, uniteCible) { |
|
|
|
|
|
let celsius = valeur; |
|
|
if (uniteSource === 'fahrenheit') { |
|
|
celsius = (valeur - 32) * 5/9; |
|
|
} else if (uniteSource === 'kelvin') { |
|
|
celsius = valeur - 273.15; |
|
|
} |
|
|
|
|
|
|
|
|
if (uniteCible === 'fahrenheit') { |
|
|
return celsius * 9/5 + 32; |
|
|
} else if (uniteCible === 'kelvin') { |
|
|
return celsius + 273.15; |
|
|
} |
|
|
|
|
|
return celsius; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekohis = { |
|
|
|
|
|
|
|
|
|
|
|
historique: [], |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ajouter: function(operation, resultat, parametres = []) { |
|
|
const entree = { |
|
|
id: this.historique.length + 1, |
|
|
operation: operation, |
|
|
resultat: resultat, |
|
|
parametres: parametres, |
|
|
timestamp: new Date(), |
|
|
date: new Date().toLocaleString() |
|
|
}; |
|
|
|
|
|
this.historique.push(entree); |
|
|
return entree; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
obtenirHistorique: function() { |
|
|
return this.historique; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
obtenirParId: function(id) { |
|
|
return this.historique.find(entree => entree.id === id); |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
effacer: function() { |
|
|
this.historique = []; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reutiliser: function(id) { |
|
|
const calcul = this.obtenirParId(id); |
|
|
if (!calcul) { |
|
|
throw new Error('nekohis.reutiliser: Calcul non trouvé.'); |
|
|
} |
|
|
return calcul.resultat; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekalgo = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
descenteGradient: function(func, gradient, x0, tauxApprentissage = 0.01, maxIterations = 1000) { |
|
|
if (typeof func !== 'function' || typeof gradient !== 'function') { |
|
|
throw new Error('nekalgo.descenteGradient: Fonction et gradient requis.'); |
|
|
} |
|
|
|
|
|
let x = x0; |
|
|
const historique = []; |
|
|
|
|
|
for (let i = 0; i < maxIterations; i++) { |
|
|
const grad = gradient(x); |
|
|
const nouveauX = x - tauxApprentissage * grad; |
|
|
|
|
|
historique.push({ |
|
|
iteration: i + 1, |
|
|
x: x, |
|
|
fx: func(x), |
|
|
gradient: grad |
|
|
}); |
|
|
|
|
|
if (Math.abs(nouveauX - x) < 1e-8) { |
|
|
return { |
|
|
minimum: nouveauX, |
|
|
valeurMinimum: func(nouveauX), |
|
|
iterations: historique, |
|
|
converge: true |
|
|
}; |
|
|
} |
|
|
|
|
|
x = nouveauX; |
|
|
} |
|
|
|
|
|
return { |
|
|
minimum: x, |
|
|
valeurMinimum: func(x), |
|
|
iterations: historique, |
|
|
converge: false |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rechercheBruteForce: function(func, a, b, pas = 0.01) { |
|
|
let xOptimal = a; |
|
|
let valeurOptimale = func(a); |
|
|
|
|
|
for (let x = a; x <= b; x += pas) { |
|
|
const valeur = func(x); |
|
|
if (valeur < valeurOptimale) { |
|
|
valeurOptimale = valeur; |
|
|
xOptimal = x; |
|
|
} |
|
|
} |
|
|
|
|
|
return { |
|
|
minimum: xOptimal, |
|
|
valeurMinimum: valeurOptimale, |
|
|
intervalle: [a, b], |
|
|
pas: pas |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekeit = { |
|
|
|
|
|
|
|
|
|
|
|
algorithmes: new Map(), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
creer: function(nom, algorithme, description = '') { |
|
|
if (typeof nom !== 'string' || typeof algorithme !== 'function') { |
|
|
throw new Error('nekeit.creer: Nom et algorithme requis.'); |
|
|
} |
|
|
|
|
|
this.algorithmes.set(nom, { |
|
|
algorithme: algorithme, |
|
|
description: description, |
|
|
creeLe: new Date(), |
|
|
executions: 0 |
|
|
}); |
|
|
|
|
|
return true; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
executer: function(nom, ...args) { |
|
|
const algo = this.algorithmes.get(nom); |
|
|
if (!algo) { |
|
|
throw new Error('nekeit.executer: Algorithme non trouvé.'); |
|
|
} |
|
|
|
|
|
algo.executions++; |
|
|
try { |
|
|
return algo.algorithme.apply(null, args); |
|
|
} catch (error) { |
|
|
throw new Error(`nekeit.executer: Erreur dans ${nom}: ${error.message}`); |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lister: function() { |
|
|
return Array.from(this.algorithmes.entries()).map(([nom, info]) => ({ |
|
|
nom: nom, |
|
|
description: info.description, |
|
|
executions: info.executions, |
|
|
creeLe: info.creeLe |
|
|
})); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const neksrar = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
coutTransport: function(distance, coutParKm, poids = 1) { |
|
|
if (typeof distance !== 'number' || typeof coutParKm !== 'number' || |
|
|
distance < 0 || coutParKm < 0) { |
|
|
throw new Error('neksrar.coutTransport: Paramètres invalides.'); |
|
|
} |
|
|
|
|
|
const coutBase = distance * coutParKm; |
|
|
const coutPoids = poids > 10 ? (poids - 10) * 0.1 * coutBase : 0; |
|
|
const coutTotal = coutBase + coutPoids; |
|
|
|
|
|
return { |
|
|
distance: distance, |
|
|
coutParKm: coutParKm, |
|
|
poids: poids, |
|
|
coutBase: coutBase, |
|
|
coutPoids: coutPoids, |
|
|
coutTotal: coutTotal |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
coutStockage: function(volume, duree, coutParM3Jour) { |
|
|
const coutTotal = volume * duree * coutParM3Jour; |
|
|
|
|
|
return { |
|
|
volume: volume, |
|
|
duree: duree, |
|
|
coutParM3Jour: coutParM3Jour, |
|
|
coutTotal: coutTotal |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekgef = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculerBFR: function(stocks, creancesClients, dettesFournisseurs) { |
|
|
const bfr = stocks + creancesClients - dettesFournisseurs; |
|
|
|
|
|
return { |
|
|
stocks: stocks, |
|
|
creancesClients: creancesClients, |
|
|
dettesFournisseurs: dettesFournisseurs, |
|
|
bfr: bfr, |
|
|
interpretation: bfr > 0 ? 'Besoin de financement' : 'Excédent de financement' |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculerFRNG: function(capitauxPermanents, immobilisations) { |
|
|
const frng = capitauxPermanents - immobilisations; |
|
|
|
|
|
return { |
|
|
capitauxPermanents: capitauxPermanents, |
|
|
immobilisations: immobilisations, |
|
|
frng: frng, |
|
|
interpretation: frng > 0 ? 'Équilibre financier' : 'Déséquilibre financier' |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculerTresorerieNette: function(frng, bfr) { |
|
|
const tresorerieNette = frng - bfr; |
|
|
|
|
|
return { |
|
|
frng: frng, |
|
|
bfr: bfr, |
|
|
tresorerieNette: tresorerieNette, |
|
|
interpretation: tresorerieNette > 0 ? 'Trésorerie positive' : 'Trésorerie négative' |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekpo = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
amortissementLineaire: function(valeurInitiale, dureeVie, valeurResiduelle = 0) { |
|
|
const baseAmortissable = valeurInitiale - valeurResiduelle; |
|
|
const annuiteAmortissement = baseAmortissable / dureeVie; |
|
|
|
|
|
const plan = []; |
|
|
let valeurComptable = valeurInitiale; |
|
|
|
|
|
for (let annee = 1; annee <= dureeVie; annee++) { |
|
|
valeurComptable -= annuiteAmortissement; |
|
|
plan.push({ |
|
|
annee: annee, |
|
|
annuiteAmortissement: annuiteAmortissement, |
|
|
valeurComptable: Math.max(valeurComptable, valeurResiduelle) |
|
|
}); |
|
|
} |
|
|
|
|
|
return { |
|
|
valeurInitiale: valeurInitiale, |
|
|
dureeVie: dureeVie, |
|
|
valeurResiduelle: valeurResiduelle, |
|
|
annuiteAmortissement: annuiteAmortissement, |
|
|
plan: plan |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plusMoinsValue: function(prixCession, valeurComptable) { |
|
|
const plusMoinsValue = prixCession - valeurComptable; |
|
|
|
|
|
return { |
|
|
prixCession: prixCession, |
|
|
valeurComptable: valeurComptable, |
|
|
plusMoinsValue: plusMoinsValue, |
|
|
type: plusMoinsValue > 0 ? 'Plus-value' : 'Moins-value' |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const nekia = { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculerTVA: function(montantHT, tauxTVA = 20) { |
|
|
const montantTVA = montantHT * tauxTVA / 100; |
|
|
const montantTTC = montantHT + montantTVA; |
|
|
|
|
|
return { |
|
|
montantHT: montantHT, |
|
|
tauxTVA: tauxTVA, |
|
|
montantTVA: montantTVA, |
|
|
montantTTC: montantTTC |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculerHT: function(montantTTC, tauxTVA = 20) { |
|
|
const montantHT = montantTTC / (1 + tauxTVA / 100); |
|
|
const montantTVA = montantTTC - montantHT; |
|
|
|
|
|
return { |
|
|
montantTTC: montantTTC, |
|
|
tauxTVA: tauxTVA, |
|
|
montantHT: montantHT, |
|
|
montantTVA: montantTVA |
|
|
}; |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculerInflation: function(valeurInitiale, valeurFinale, annees = 1) { |
|
|
const tauxInflation = Math.pow(valeurFinale / valeurInitiale, 1 / annees) - 1; |
|
|
const tauxPourcentage = tauxInflation * 100; |
|
|
|
|
|
return { |
|
|
valeurInitiale: valeurInitiale, |
|
|
valeurFinale: valeurFinale, |
|
|
annees: annees, |
|
|
tauxInflation: tauxInflation, |
|
|
tauxPourcentage: tauxPourcentage |
|
|
}; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
module.exports = { |
|
|
nekadd, |
|
|
neksub, |
|
|
nekmult, |
|
|
nekdiv, |
|
|
nekIsPairOuImpair, |
|
|
nekorandom, |
|
|
nekofibona, |
|
|
nekpremier, |
|
|
nekopi, |
|
|
nekracine, |
|
|
nekodouble, |
|
|
nekomoitie, |
|
|
nekdegres, |
|
|
|
|
|
nekFacteurs, |
|
|
nekopuissance, |
|
|
nekmed, |
|
|
nekmoy, |
|
|
neky, |
|
|
neklet, |
|
|
nekpourcentage, |
|
|
nektalor, |
|
|
nektales, |
|
|
nekproba, |
|
|
|
|
|
nekbel, |
|
|
nekcreative, |
|
|
nekorror, |
|
|
|
|
|
nekdraw, |
|
|
nekril, |
|
|
nekocust, |
|
|
nekrect, |
|
|
nekpap, |
|
|
nekdesar, |
|
|
|
|
|
nekident, |
|
|
nekaqua, |
|
|
nekfrac, |
|
|
nektin, |
|
|
nekalpha, |
|
|
nekbeta, |
|
|
nekomega, |
|
|
nekcopare, |
|
|
nekdone, |
|
|
nekarin, |
|
|
|
|
|
nekgrap, |
|
|
nekoser, |
|
|
neka, |
|
|
nekoma, |
|
|
nekyu, |
|
|
nekonew, |
|
|
nekcarlo, |
|
|
nekinterac, |
|
|
nekconvert, |
|
|
nekohis, |
|
|
nekalgo, |
|
|
nekeit, |
|
|
neksrar, |
|
|
nekgef, |
|
|
nekpo, |
|
|
nekia |
|
|
}; |
|
|
|