-
Notifications
You must be signed in to change notification settings - Fork 312
Add FormatNumbers Extension #2036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
8ad2ad2
7ce2c75
91393fc
b93ceb9
f7e72e6
473a4e9
ebf204a
fcf4c7c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| // Name: Format Numbers | ||
| // ID: dogeiscutformatnumbers | ||
Brackets-Coder marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Description: Format large numbers into AD standard, fixed decimal, comma separated, or scientific notation. | ||
| // By: DogeisCut <https://scratch.mit.edu/users/dogeiscut/> | ||
| // License: MIT | ||
yuri-kiss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Version V.2.0.2 | ||
|
|
||
| // TODO: | ||
| // - Editor Icon | ||
| // - BigInt Support | ||
| // - Time notation, decimal count defines how many milliseconds show. | ||
|
|
||
| (function (Scratch) { | ||
| "use strict"; | ||
|
|
||
| const Cast = Scratch.Cast; | ||
|
|
||
| const Formats = { | ||
| AD_STANDARD: "AD standard", | ||
| FIXED_DECIMAL: "fixed decimal", | ||
| COMMA_SEPERATED: "comma separated", | ||
| SCIENTIFIC_NOTATION: "scientific notation", | ||
| }; | ||
|
|
||
| class FormatNumbers { | ||
| constructor() { | ||
| this.notation = "AD standard"; | ||
| this.decimalPlaces = 2; | ||
| } | ||
|
|
||
| convertToADStandard(number, decimalPlaces = 2) { | ||
| if (typeof number !== "number" || isNaN(number)) { | ||
| return "Invalid Input"; | ||
| } | ||
|
|
||
| if (!isFinite(number)) { | ||
| return number.toString(); | ||
| } | ||
|
|
||
| if (number === 0) { | ||
| return "0"; | ||
| } | ||
|
|
||
| const kMBd = [ | ||
| "", | ||
| "K", | ||
| "M", | ||
| "B", | ||
| "T", | ||
| "Qa", | ||
| "Qt", | ||
| "Sx", | ||
| "Sp", | ||
| "Oc", | ||
| "No", | ||
| "Dc", | ||
| ]; | ||
| const unitPrefixes = ["U", "D", "T", "Qa", "Qt", "Sx", "Sp", "O", "N"]; | ||
Brackets-Coder marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const tensPrefixes = [ | ||
| "Dc", | ||
| "Vg", | ||
| "Tg", | ||
| "Qd", | ||
| "Qi", | ||
| "Se", | ||
| "St", | ||
| "Og", | ||
| "Nn", | ||
| ]; | ||
| const hundredsPrefixes = [ | ||
| "Ce", | ||
| "Dn", | ||
| "Tc", | ||
| "Qe", | ||
| "Qu", | ||
| "Sc", | ||
| "Si", | ||
| "Oe", | ||
| "Ne", | ||
| ]; | ||
| const tier2Illions = ["MI", "MC", "NA", "PC", "FM", "AT", "ZP"]; | ||
| const tier2Cutoff = 3003 * tier2Illions.length; | ||
| if (Math.log10(Math.abs(number)) > tier2Cutoff) { | ||
| return `Il(${number})`; | ||
| } | ||
|
|
||
| if (Math.abs(number) < 1000) { | ||
| return number.toFixed(decimalPlaces).replace(/\.?0+$/, ""); | ||
| } | ||
|
|
||
| const tier = Math.max(0, Math.floor(Math.log10(Math.abs(number)) / 3)); | ||
|
|
||
| if (tier <= 11) { | ||
| const scaledNumber = number / Math.pow(10, tier * 3); | ||
| return ( | ||
| scaledNumber.toFixed(decimalPlaces).replace(/\.?0+$/, "") + kMBd[tier] | ||
| ); | ||
| } | ||
|
|
||
| const illionNumber = Math.floor(Math.log10(Math.abs(number)) / 3); | ||
| let illionString = ""; | ||
|
|
||
| if (illionNumber <= 999) { | ||
| const hundreds = Math.floor(illionNumber / 100); | ||
| const tens = Math.floor((illionNumber % 100) / 10); | ||
| const units = illionNumber % 10; | ||
|
|
||
| illionString = | ||
| (hundreds > 0 ? hundredsPrefixes[hundreds - 1] : "") + | ||
| (tens > 0 ? tensPrefixes[tens - 1] : "") + | ||
| (units > 0 ? unitPrefixes[units - 1] : ""); | ||
| } else { | ||
| const tier2Index = Math.floor(illionNumber / 1000); | ||
| const tier2Remainder = illionNumber % 1000; | ||
|
|
||
| if (tier2Index <= tier2Illions.length) { | ||
| illionString = tier2Illions[tier2Index - 1]; | ||
| } else { | ||
| return `Il(${number})`; | ||
| } | ||
|
|
||
| if (tier2Remainder > 0) { | ||
| const hundreds = Math.floor(tier2Remainder / 100); | ||
| const tens = Math.floor((tier2Remainder % 100) / 10); | ||
| const units = tier2Remainder % 10; | ||
|
|
||
| const remainderString = | ||
| (hundreds > 0 ? hundredsPrefixes[hundreds - 1] : "") + | ||
| (tens > 0 ? tensPrefixes[tens - 1] : "") + | ||
| (units > 0 ? unitPrefixes[units - 1] : ""); | ||
| illionString = remainderString + "-" + illionString; | ||
| } | ||
| } | ||
|
|
||
| const scaledNumber = | ||
| number / Math.pow(10, Math.floor(Math.log10(Math.abs(number)) / 3) * 3); | ||
| return ( | ||
| scaledNumber.toFixed(decimalPlaces).replace(/\.?0+$/, "") + | ||
| " " + | ||
| illionString | ||
| ); | ||
| } | ||
|
|
||
| convertToCommaSeparated(number, decimalPlaces = 2) { | ||
| return number | ||
| .toFixed(decimalPlaces) | ||
| .replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,"); | ||
| } | ||
|
|
||
| convertToScientificNotation(number, decimalPlaces = 2) { | ||
| return number.toExponential(decimalPlaces); | ||
| } | ||
|
|
||
| formatNumber(args) { | ||
| const decimals = Math.max(0, Math.min(100, Cast.toNumber(args.DECIMALS))); | ||
| switch (args.NOTATION) { | ||
| case Formats.AD_STANDARD: | ||
| return this.convertToADStandard(Cast.toNumber(args.NUM), decimals); | ||
| case Formats.COMMA_SEPERATED: | ||
| return this.convertToCommaSeparated( | ||
| Cast.toNumber(args.NUM), | ||
| decimals | ||
| ); | ||
| case Formats.SCIENTIFIC_NOTATION: | ||
| return this.convertToScientificNotation( | ||
| Cast.toNumber(args.NUM), | ||
| decimals | ||
| ); | ||
| default: | ||
| return Cast.toNumber(args.NUM).toFixed(decimals); | ||
| } | ||
| } | ||
|
|
||
| getInfo() { | ||
| return { | ||
| id: "formatNumbers", | ||
yuri-kiss marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| name: Scratch.translate("Format Numbers"), | ||
| color1: "#419873", | ||
| color2: "#4CA981", | ||
| blocks: [ | ||
| { | ||
| opcode: "formatNumber", | ||
| text: Scratch.translate( | ||
| "format number [NUM] to notation [NOTATION] with [DECIMALS] decimal places" | ||
| ), | ||
| blockType: Scratch.BlockType.REPORTER, | ||
| arguments: { | ||
| NUM: { | ||
| type: Scratch.ArgumentType.NUMBER, | ||
| defaultValue: 1000, | ||
| }, | ||
| NOTATION: { | ||
| type: Scratch.ArgumentType.STRING, | ||
| menu: "notationOptions", | ||
| defaultValue: "AD standard", | ||
| }, | ||
| DECIMALS: { | ||
| type: Scratch.ArgumentType.NUMBER, | ||
| defaultValue: 2, | ||
| }, | ||
| }, | ||
| }, | ||
| ], | ||
| menus: { | ||
| notationOptions: { | ||
| acceptReporters: false, | ||
| items: [ | ||
| { | ||
| text: Scratch.translate("AD standard"), | ||
| value: Formats.AD_STANDARD, | ||
| }, | ||
| { | ||
| text: Scratch.translate("fixed decimal"), | ||
| value: Formats.FIXED_DECIMAL, | ||
| }, | ||
| { | ||
| text: Scratch.translate("comma separated"), | ||
| value: Formats.COMMA_SEPERATED, | ||
| }, | ||
| { | ||
| text: Scratch.translate("scientific notation"), | ||
| value: Formats.SCIENTIFIC_NOTATION, | ||
| }, | ||
| ], | ||
| }, | ||
| }, | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| Scratch.extensions.register(new FormatNumbers()); | ||
| })(Scratch); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically extension images aren't supposed to contain text because of translation reasons, but I think this one is okay because it uses Arabic numerals which are (generally speaking) somewhat universal? I don't know. Second opinion would be great
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. imo numbers wouldn't be considered text for thumbnails.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's what I was thinking too
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. though ideally this should be an SVG
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would've liked to make this an SVG but unfortunately, I don't believe Dillon has an SVG version. Guess I could try to re-create it if it is really necissary? |
Uh oh!
There was an error while loading. Please reload this page.