@quenty/metricutils 2.4.3 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -54
- package/README.md +80 -2
- package/deploy.nevermore.json +10 -0
- package/package.json +22 -4
- package/src/Shared/Definitions/MetricUnitDefinitions.lua +1082 -0
- package/src/Shared/Definitions/MetricUnitDefinitions.spec.lua +55 -0
- package/src/Shared/Definitions/MetricUnitDimensionUtils.lua +164 -0
- package/src/Shared/Definitions/MetricUnitDimensionUtils.spec.lua +49 -0
- package/src/Shared/Definitions/MetricUnitKinds.lua +237 -0
- package/src/Shared/Definitions/MetricUnitKinds.spec.lua +51 -0
- package/src/Shared/Formatting/MetricUnitDisplayUnitUtils.lua +129 -0
- package/src/Shared/Formatting/MetricUnitFormatUtils.lua +924 -0
- package/src/Shared/Formatting/MetricUnitFormatUtils.spec.lua +280 -0
- package/src/Shared/Formatting/RxMetricUnitFormatUtils.lua +62 -0
- package/src/Shared/Localization/MetricUnitFallbackStrings.lua +289 -0
- package/src/Shared/Localization/MetricUnitFallbackStrings.spec.lua +82 -0
- package/src/Shared/Localization/MetricUnitTranslator/ar.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/de.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/en.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/es.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/fr.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/id.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/init.lua +92 -0
- package/src/Shared/Localization/MetricUnitTranslator/it.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/ja.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/ko.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/pl.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/pt.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/ru.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/th.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/tr.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/vi.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/zh-cn.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator/zh-tw.json.txt +182 -0
- package/src/Shared/Localization/MetricUnitTranslator.spec.lua +309 -0
- package/src/Shared/Localization/PluralCategoryUtils.lua +103 -0
- package/src/Shared/Localization/PluralCategoryUtils.spec.lua +77 -0
- package/src/Shared/Logarithmic/DecibelUtils.lua +72 -0
- package/src/Shared/Logarithmic/DecibelUtils.spec.lua +35 -0
- package/src/Shared/MetricUnit.Angles.spec.lua +80 -0
- package/src/Shared/MetricUnit.Customary.spec.lua +104 -0
- package/src/Shared/MetricUnit.Derived.spec.lua +173 -0
- package/src/Shared/MetricUnit.Display.spec.lua +153 -0
- package/src/Shared/MetricUnit.Electrical.spec.lua +114 -0
- package/src/Shared/MetricUnit.Math.spec.lua +112 -0
- package/src/Shared/MetricUnit.Roblox.spec.lua +34 -0
- package/src/Shared/MetricUnit.SI.spec.lua +127 -0
- package/src/Shared/MetricUnit.Spring.spec.lua +94 -0
- package/src/Shared/MetricUnit.Temperature.spec.lua +212 -0
- package/src/Shared/MetricUnit.Time.spec.lua +202 -0
- package/src/Shared/MetricUnit.Units.spec.lua +210 -0
- package/src/Shared/MetricUnit.lua +1730 -0
- package/src/Shared/MetricUnit.spec.lua +362 -0
- package/src/Shared/MetricUtils.lua +47 -16
- package/src/Shared/MetricUtils.spec.lua +76 -0
- package/src/Shared/Parsing/MetricUnitParseUtils.lua +799 -0
- package/src/Shared/Parsing/MetricUnitParseUtils.spec.lua +189 -0
- package/src/Shared/Systems/MetricUnitSystem.lua +322 -0
- package/src/Shared/Systems/MetricUnitSystem.spec.lua +181 -0
- package/src/Shared/Systems/MetricUnitSystems.lua +225 -0
- package/src/jest.config.lua +3 -0
- package/src/node_modules.project.json +7 -0
- package/test/default.project.json +25 -0
- package/test/scripts/Server/ServerMain.server.lua +14 -0
|
@@ -0,0 +1,1082 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--[=[
|
|
3
|
+
Every unit [MetricUnit] can be made in, read in, parsed from and written in. This list is where a unit is
|
|
4
|
+
declared: its id, dimensions, size in SI base units, symbol, measurement system, English names and the other
|
|
5
|
+
text it may be typed as. [MetricUnit], [MetricUnitFormatUtils], [MetricUnitParseUtils] and
|
|
6
|
+
[MetricUnitFallbackStrings] all read it. Symbols are the SI ones (or the customary ones for US and imperial
|
|
7
|
+
units), which do not change with the locale.
|
|
8
|
+
|
|
9
|
+
To add a unit:
|
|
10
|
+
|
|
11
|
+
1. Add a row to the `define` call for its dimension and system below. See [UnitRow] for the fields. Give an SI
|
|
12
|
+
unit `prefixes` rather than adding its prefixed forms: `kilo`, `nano` and the rest are made from it.
|
|
13
|
+
2. Add its id to the `UnitId` union, with any prefixed forms games commonly name. luau-lsp rejects a row whose
|
|
14
|
+
id is missing from it; other prefixed ids work at runtime.
|
|
15
|
+
3. Add it to a system's display units in [MetricUnitSystems] if it should be picked by size.
|
|
16
|
+
4. If it is written by name, add `units.<id>.long.<category>` and `units.<id>.short.<category>` for all six
|
|
17
|
+
plural categories to every `Localization/MetricUnitTranslator/<locale>.json.txt`: English from this row, the
|
|
18
|
+
other languages from CLDR's unit patterns. Prefixed forms need no entry; they are written from the
|
|
19
|
+
`prefixes` section and the unit's own entry.
|
|
20
|
+
5. Only for a unit games construct constantly, add a named constructor on [MetricUnit].
|
|
21
|
+
|
|
22
|
+
The specs catch a named unit without English names or translation keys, and a unit that does not round-trip
|
|
23
|
+
through [MetricUnit.new] and [MetricUnit.In].
|
|
24
|
+
|
|
25
|
+
@class MetricUnitDefinitions
|
|
26
|
+
]=]
|
|
27
|
+
|
|
28
|
+
local require = require(script.Parent.loader).load(script)
|
|
29
|
+
|
|
30
|
+
local MetricUnitDimensionUtils = require("MetricUnitDimensionUtils")
|
|
31
|
+
local MetricUnitKinds = require("MetricUnitKinds")
|
|
32
|
+
local Time = require("Time")
|
|
33
|
+
|
|
34
|
+
local MetricUnitDefinitions = {}
|
|
35
|
+
|
|
36
|
+
--[=[
|
|
37
|
+
A unit's id: the singular, camelCase name of the unit. Every id has an entry in [MetricUnitDefinitions]; reading,
|
|
38
|
+
formatting and [MetricUnit.new] all take it, so a typo is a type error.
|
|
39
|
+
|
|
40
|
+
@type UnitId "microsecond" | "millisecond" | "second" | "minute" | "hour" | "day" | "week" | "month" | "quarter" | "year" | "perSecond" | "perMinute" | "perHour" | "perDay" | "perWeek" | "perMonth" | "perYear" | "hertz" | "percent" | "permille" | "millimeter" | "centimeter" | "meter" | "kilometer" | "inch" | "foot" | "yard" | "mile" | "stud" | "squareMillimeter" | "squareCentimeter" | "squareMeter" | "hectare" | "squareKilometer" | "squareFoot" | "acre" | "milliliter" | "liter" | "cubicMeter" | "usFluidOunce" | "usGallon" | "imperialGallon" | "bit" | "kilobit" | "megabit" | "gigabit" | "byte" | "kilobyte" | "megabyte" | "gigabyte" | "kibibyte" | "mebibyte" | "gibibyte" | "bitPerSecond" | "kilobitPerSecond" | "megabitPerSecond" | "gigabitPerSecond" | "bytePerSecond" | "kilobytePerSecond" | "milligram" | "gram" | "kilogram" | "tonne" | "ounce" | "pound" | "stone" | "robloxMassUnit" | "meterPerSecond" | "kilometerPerHour" | "milePerHour" | "knot" | "studPerSecond" | "meterPerSecondSquared" | "studPerSecondSquared" | "newton" | "kilonewton" | "meganewton" | "poundForce" | "joule" | "kilojoule" | "megajoule" | "kilowattHour" | "kilocalorie" | "watt" | "kilowatt" | "megawatt" | "pascal" | "kilopascal" | "megapascal" | "bar" | "poundForcePerSquareInch" | "kilogramPerCubicMeter" | "gramPerCubicCentimeter" | "kelvin" | "celsius" | "fahrenheit" | "radian" | "degree" | "revolution" | "radianPerSecond" | "degreePerSecond" | "revolutionPerMinute" | "radianPerSecondSquared" | "microampere" | "milliampere" | "ampere" | "coulomb" | "millivolt" | "volt" | "kilovolt" | "ohm" | "kilohm" | "megohm" | "siemens" | "picofarad" | "nanofarad" | "microfarad" | "farad" | "microhenry" | "millihenry" | "henry" | "weber" | "millitesla" | "tesla" | "nanometer" | "micrometer" | "centiliter" | "deciliter" | "terabyte" | "petabyte" | "microgram" | "milliwatt" | "gigawatt" | "kilohertz" | "megahertz" | "gigahertz" | "becquerel" | "mole" | "millimole" | "micromole" | "kilomole" | "gramPerMole" | "molePerLiter" | "millimolePerLiter" | "katal" | "candela" | "steradian" | "lumen" | "lux" | "kilolux" | "gray" | "milligray" | "sievert" | "millisievert" | "microsievert" | "nauticalMile" | "literPer100Kilometers" | "squareInch" | "squareYard" | "squareMile" | "cubicInch" | "cubicFoot" | "cubicYard" | "usTeaspoon" | "usTablespoon" | "usCup" | "usPint" | "usQuart" | "imperialFluidOunce" | "imperialPint" | "imperialQuart" | "shortTon" | "footPerSecond" | "footPerSecondSquared" | "newtonMeter" | "britishThermalUnit" | "poundFoot" | "metricHorsepower" | "horsepower" | "inchOfMercury" | "poundPerCubicFoot" | "kilometerPerLiter" | "milePerUsGallon" | "milePerImperialGallon" | "rankine"
|
|
41
|
+
@within MetricUnitDefinitions
|
|
42
|
+
]=]
|
|
43
|
+
export type UnitId =
|
|
44
|
+
"microsecond"
|
|
45
|
+
| "millisecond"
|
|
46
|
+
| "second"
|
|
47
|
+
| "minute"
|
|
48
|
+
| "hour"
|
|
49
|
+
| "day"
|
|
50
|
+
| "week"
|
|
51
|
+
| "month"
|
|
52
|
+
| "quarter"
|
|
53
|
+
| "year"
|
|
54
|
+
| "perSecond"
|
|
55
|
+
| "perMinute"
|
|
56
|
+
| "perHour"
|
|
57
|
+
| "perDay"
|
|
58
|
+
| "perWeek"
|
|
59
|
+
| "perMonth"
|
|
60
|
+
| "perYear"
|
|
61
|
+
| "hertz"
|
|
62
|
+
| "percent"
|
|
63
|
+
| "permille"
|
|
64
|
+
| "millimeter"
|
|
65
|
+
| "centimeter"
|
|
66
|
+
| "meter"
|
|
67
|
+
| "kilometer"
|
|
68
|
+
| "inch"
|
|
69
|
+
| "foot"
|
|
70
|
+
| "yard"
|
|
71
|
+
| "mile"
|
|
72
|
+
| "stud"
|
|
73
|
+
| "squareMillimeter"
|
|
74
|
+
| "squareCentimeter"
|
|
75
|
+
| "squareMeter"
|
|
76
|
+
| "hectare"
|
|
77
|
+
| "squareKilometer"
|
|
78
|
+
| "squareFoot"
|
|
79
|
+
| "acre"
|
|
80
|
+
| "milliliter"
|
|
81
|
+
| "liter"
|
|
82
|
+
| "cubicMeter"
|
|
83
|
+
| "usFluidOunce"
|
|
84
|
+
| "usGallon"
|
|
85
|
+
| "imperialGallon"
|
|
86
|
+
| "bit"
|
|
87
|
+
| "kilobit"
|
|
88
|
+
| "megabit"
|
|
89
|
+
| "gigabit"
|
|
90
|
+
| "byte"
|
|
91
|
+
| "kilobyte"
|
|
92
|
+
| "megabyte"
|
|
93
|
+
| "gigabyte"
|
|
94
|
+
| "kibibyte"
|
|
95
|
+
| "mebibyte"
|
|
96
|
+
| "gibibyte"
|
|
97
|
+
| "bitPerSecond"
|
|
98
|
+
| "kilobitPerSecond"
|
|
99
|
+
| "megabitPerSecond"
|
|
100
|
+
| "gigabitPerSecond"
|
|
101
|
+
| "bytePerSecond"
|
|
102
|
+
| "kilobytePerSecond"
|
|
103
|
+
| "milligram"
|
|
104
|
+
| "gram"
|
|
105
|
+
| "kilogram"
|
|
106
|
+
| "tonne"
|
|
107
|
+
| "ounce"
|
|
108
|
+
| "pound"
|
|
109
|
+
| "stone"
|
|
110
|
+
| "robloxMassUnit"
|
|
111
|
+
| "meterPerSecond"
|
|
112
|
+
| "kilometerPerHour"
|
|
113
|
+
| "milePerHour"
|
|
114
|
+
| "knot"
|
|
115
|
+
| "studPerSecond"
|
|
116
|
+
| "meterPerSecondSquared"
|
|
117
|
+
| "studPerSecondSquared"
|
|
118
|
+
| "newton"
|
|
119
|
+
| "kilonewton"
|
|
120
|
+
| "meganewton"
|
|
121
|
+
| "poundForce"
|
|
122
|
+
| "joule"
|
|
123
|
+
| "kilojoule"
|
|
124
|
+
| "megajoule"
|
|
125
|
+
| "kilowattHour"
|
|
126
|
+
| "kilocalorie"
|
|
127
|
+
| "watt"
|
|
128
|
+
| "kilowatt"
|
|
129
|
+
| "megawatt"
|
|
130
|
+
| "pascal"
|
|
131
|
+
| "kilopascal"
|
|
132
|
+
| "megapascal"
|
|
133
|
+
| "bar"
|
|
134
|
+
| "poundForcePerSquareInch"
|
|
135
|
+
| "kilogramPerCubicMeter"
|
|
136
|
+
| "gramPerCubicCentimeter"
|
|
137
|
+
| "kelvin"
|
|
138
|
+
| "celsius"
|
|
139
|
+
| "fahrenheit"
|
|
140
|
+
| "radian"
|
|
141
|
+
| "degree"
|
|
142
|
+
| "revolution"
|
|
143
|
+
| "radianPerSecond"
|
|
144
|
+
| "degreePerSecond"
|
|
145
|
+
| "revolutionPerMinute"
|
|
146
|
+
| "radianPerSecondSquared"
|
|
147
|
+
| "microampere"
|
|
148
|
+
| "milliampere"
|
|
149
|
+
| "ampere"
|
|
150
|
+
| "coulomb"
|
|
151
|
+
| "millivolt"
|
|
152
|
+
| "volt"
|
|
153
|
+
| "kilovolt"
|
|
154
|
+
| "ohm"
|
|
155
|
+
| "kilohm"
|
|
156
|
+
| "megohm"
|
|
157
|
+
| "siemens"
|
|
158
|
+
| "picofarad"
|
|
159
|
+
| "nanofarad"
|
|
160
|
+
| "microfarad"
|
|
161
|
+
| "farad"
|
|
162
|
+
| "microhenry"
|
|
163
|
+
| "millihenry"
|
|
164
|
+
| "henry"
|
|
165
|
+
| "weber"
|
|
166
|
+
| "millitesla"
|
|
167
|
+
| "tesla"
|
|
168
|
+
| "nanometer"
|
|
169
|
+
| "micrometer"
|
|
170
|
+
| "centiliter"
|
|
171
|
+
| "deciliter"
|
|
172
|
+
| "terabyte"
|
|
173
|
+
| "petabyte"
|
|
174
|
+
| "microgram"
|
|
175
|
+
| "milliwatt"
|
|
176
|
+
| "gigawatt"
|
|
177
|
+
| "kilohertz"
|
|
178
|
+
| "megahertz"
|
|
179
|
+
| "gigahertz"
|
|
180
|
+
| "becquerel"
|
|
181
|
+
| "mole"
|
|
182
|
+
| "millimole"
|
|
183
|
+
| "micromole"
|
|
184
|
+
| "kilomole"
|
|
185
|
+
| "gramPerMole"
|
|
186
|
+
| "molePerLiter"
|
|
187
|
+
| "millimolePerLiter"
|
|
188
|
+
| "katal"
|
|
189
|
+
| "candela"
|
|
190
|
+
| "steradian"
|
|
191
|
+
| "lumen"
|
|
192
|
+
| "lux"
|
|
193
|
+
| "kilolux"
|
|
194
|
+
| "gray"
|
|
195
|
+
| "milligray"
|
|
196
|
+
| "sievert"
|
|
197
|
+
| "millisievert"
|
|
198
|
+
| "microsievert"
|
|
199
|
+
| "nauticalMile"
|
|
200
|
+
| "literPer100Kilometers"
|
|
201
|
+
| "squareInch"
|
|
202
|
+
| "squareYard"
|
|
203
|
+
| "squareMile"
|
|
204
|
+
| "cubicInch"
|
|
205
|
+
| "cubicFoot"
|
|
206
|
+
| "cubicYard"
|
|
207
|
+
| "usTeaspoon"
|
|
208
|
+
| "usTablespoon"
|
|
209
|
+
| "usCup"
|
|
210
|
+
| "usPint"
|
|
211
|
+
| "usQuart"
|
|
212
|
+
| "imperialFluidOunce"
|
|
213
|
+
| "imperialPint"
|
|
214
|
+
| "imperialQuart"
|
|
215
|
+
| "shortTon"
|
|
216
|
+
| "footPerSecond"
|
|
217
|
+
| "footPerSecondSquared"
|
|
218
|
+
| "newtonMeter"
|
|
219
|
+
| "britishThermalUnit"
|
|
220
|
+
| "poundFoot"
|
|
221
|
+
| "metricHorsepower"
|
|
222
|
+
| "horsepower"
|
|
223
|
+
| "inchOfMercury"
|
|
224
|
+
| "poundPerCubicFoot"
|
|
225
|
+
| "kilometerPerLiter"
|
|
226
|
+
| "milePerUsGallon"
|
|
227
|
+
| "milePerImperialGallon"
|
|
228
|
+
| "rankine"
|
|
229
|
+
|
|
230
|
+
--[=[
|
|
231
|
+
A unit id, any of `@quenty/time`'s names for a time unit, such as `"hours"` or `"h"`, or a unit itself, such as
|
|
232
|
+
`MINI:GetUnit("stud")` from a [MetricUnitSystem] of the game's own scale.
|
|
233
|
+
|
|
234
|
+
@type UnitLike UnitId | Time.TimeUnit | UnitDefinition
|
|
235
|
+
@within MetricUnitDefinitions
|
|
236
|
+
]=]
|
|
237
|
+
export type UnitLike = UnitId | Time.TimeUnit | UnitDefinition
|
|
238
|
+
|
|
239
|
+
--[=[
|
|
240
|
+
The name of the [MetricUnitSystem] that declares a unit: `"metric"`, `"usCustomary"`, `"imperial"`,
|
|
241
|
+
`"usCustomaryAndImperial"` for the units the United States and Britain share (the inch, mile, pound, mph, BTU,
|
|
242
|
+
horsepower), `"roblox"`, or a game's own system. Time units and bare rates belong to none, since every system
|
|
243
|
+
shares them.
|
|
244
|
+
|
|
245
|
+
@type UnitFamily string
|
|
246
|
+
@within MetricUnitDefinitions
|
|
247
|
+
]=]
|
|
248
|
+
export type UnitFamily = string
|
|
249
|
+
|
|
250
|
+
--[=[
|
|
251
|
+
A singular and plural form of a unit's English name or phrase.
|
|
252
|
+
|
|
253
|
+
@interface UnitForms
|
|
254
|
+
.one string
|
|
255
|
+
.other string
|
|
256
|
+
@within MetricUnitDefinitions
|
|
257
|
+
]=]
|
|
258
|
+
export type UnitForms = { one: string, other: string }
|
|
259
|
+
|
|
260
|
+
--[=[
|
|
261
|
+
One unit.
|
|
262
|
+
|
|
263
|
+
- `factor` is its size in SI base units: seconds, metres, kilograms, bytes, kelvin, radians, amperes, moles or
|
|
264
|
+
candelas, or their product for a derived unit, so a newton is 1 (kg·m/s²) and a kilowatt-hour 3,600,000 (J).
|
|
265
|
+
- `names` is its American English name, for units written by name. Commonwealth spelling (metre, litre, tonne)
|
|
266
|
+
is derived.
|
|
267
|
+
- `shortTemplates` replaces the default short phrase, the symbol after a space, where that reads wrongly
|
|
268
|
+
(`45%`, `45°`, `1 stud`). `%s` is the number.
|
|
269
|
+
- `duration` marks the time units, which durations are written in.
|
|
270
|
+
- `prefix` is set on a unit made from a prefix and another unit, such as `kilometer`.
|
|
271
|
+
|
|
272
|
+
The other fields are as in [UnitRow].
|
|
273
|
+
|
|
274
|
+
@interface UnitDefinition
|
|
275
|
+
.id UnitId
|
|
276
|
+
.dimensions Dimensions
|
|
277
|
+
.factor number
|
|
278
|
+
.symbol string
|
|
279
|
+
.system UnitFamily?
|
|
280
|
+
.names UnitForms?
|
|
281
|
+
.shortTemplates UnitForms?
|
|
282
|
+
.aliases { string }?
|
|
283
|
+
.zero number?
|
|
284
|
+
.per UnitId?
|
|
285
|
+
.duration boolean?
|
|
286
|
+
.prefix UnitPrefixOf?
|
|
287
|
+
@within MetricUnitDefinitions
|
|
288
|
+
]=]
|
|
289
|
+
export type UnitDefinition = {
|
|
290
|
+
id: UnitId,
|
|
291
|
+
dimensions: MetricUnitDimensionUtils.Dimensions,
|
|
292
|
+
factor: number,
|
|
293
|
+
symbol: string,
|
|
294
|
+
system: UnitFamily?,
|
|
295
|
+
names: UnitForms?,
|
|
296
|
+
shortTemplates: UnitForms?,
|
|
297
|
+
aliases: { string }?,
|
|
298
|
+
zero: number?,
|
|
299
|
+
per: UnitId?,
|
|
300
|
+
duration: boolean?,
|
|
301
|
+
prefix: UnitPrefixOf?,
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
--[=[
|
|
305
|
+
For a unit made by prefixing another, the prefix's name and the unit it prefixes: `kilometer` is `kilo` and
|
|
306
|
+
`meter`. A translator writes it from those two when it has no entry for the unit itself.
|
|
307
|
+
|
|
308
|
+
@interface UnitPrefixOf
|
|
309
|
+
.name string
|
|
310
|
+
.base UnitId
|
|
311
|
+
@within MetricUnitDefinitions
|
|
312
|
+
]=]
|
|
313
|
+
export type UnitPrefixOf = { name: string, base: UnitId }
|
|
314
|
+
|
|
315
|
+
--[=[
|
|
316
|
+
One row of the list below, for a unit of the kind (`"length"`, `"speed"`) and system its `define` call gives.
|
|
317
|
+
|
|
318
|
+
- `factor` is its size in SI base units.
|
|
319
|
+
- `name` is its American English singular, for units written by name; `plural` defaults to `name` plus "s".
|
|
320
|
+
Time units are written with `@quenty/time`'s words and bare rates with per phrases, so they have none.
|
|
321
|
+
- `short` replaces the symbol-after-a-space short phrase, as one template or a singular and plural.
|
|
322
|
+
- `aliases` is other text it may be typed as when parsed, such as `"kph"`.
|
|
323
|
+
- `zero` is where the unit's scale starts, in base units. A unit with one is a scale whose readings are points:
|
|
324
|
+
[MetricUnit.new] makes absolute values in it. Only the temperature scales have one.
|
|
325
|
+
- `per` is the time unit a bare rate such as `perHour` counts per. Hertz is a rate too, but is written by name.
|
|
326
|
+
- `prefixes` makes a unit for each prefix of a [PrefixSet]: `meter` with `"si"` makes `kilometer`, `nanometer`
|
|
327
|
+
and the rest, with names, symbols and aliases from the unit's. A unit declared outright keeps its own row.
|
|
328
|
+
- `elidesPrefixVowel` drops a prefix's final vowel before the unit, as SI writes `kilohm` and `megohm`.
|
|
329
|
+
|
|
330
|
+
@interface UnitRow
|
|
331
|
+
.id UnitId
|
|
332
|
+
.factor number
|
|
333
|
+
.symbol string
|
|
334
|
+
.name string?
|
|
335
|
+
.plural string?
|
|
336
|
+
.short (string | UnitForms)?
|
|
337
|
+
.aliases { string }?
|
|
338
|
+
.zero number?
|
|
339
|
+
.per UnitId?
|
|
340
|
+
.prefixes PrefixSet?
|
|
341
|
+
.elidesPrefixVowel boolean?
|
|
342
|
+
@within MetricUnitDefinitions
|
|
343
|
+
]=]
|
|
344
|
+
export type UnitRow = {
|
|
345
|
+
id: UnitId,
|
|
346
|
+
factor: number,
|
|
347
|
+
symbol: string,
|
|
348
|
+
name: string?,
|
|
349
|
+
plural: string?,
|
|
350
|
+
short: (string | UnitForms)?,
|
|
351
|
+
aliases: { string }?,
|
|
352
|
+
zero: number?,
|
|
353
|
+
per: UnitId?,
|
|
354
|
+
prefixes: PrefixSet?,
|
|
355
|
+
elidesPrefixVowel: boolean?,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
--[=[
|
|
359
|
+
A metric or binary prefix: `kilo` is `k` and 1000.
|
|
360
|
+
|
|
361
|
+
@interface Prefix
|
|
362
|
+
.name string
|
|
363
|
+
.symbol string
|
|
364
|
+
.factor number
|
|
365
|
+
@within MetricUnitDefinitions
|
|
366
|
+
]=]
|
|
367
|
+
export type Prefix = { name: string, symbol: string, factor: number }
|
|
368
|
+
|
|
369
|
+
--[=[
|
|
370
|
+
Which prefixes a unit takes: `"si"` all twenty-four SI prefixes, `"siMultiples"` only those of 10 and above (no
|
|
371
|
+
millibytes), and `"siMultiplesAndBinary"` those and the binary ones (`KiB`, `MiB`).
|
|
372
|
+
|
|
373
|
+
@type PrefixSet "si" | "siMultiples" | "siMultiplesAndBinary"
|
|
374
|
+
@within MetricUnitDefinitions
|
|
375
|
+
]=]
|
|
376
|
+
export type PrefixSet = "si" | "siMultiples" | "siMultiplesAndBinary"
|
|
377
|
+
|
|
378
|
+
--[=[
|
|
379
|
+
Metres in a Roblox stud, as Roblox documents it against the default avatar: 28 cm.
|
|
380
|
+
|
|
381
|
+
@prop ROBLOX_METERS_PER_STUD number
|
|
382
|
+
@within MetricUnitDefinitions
|
|
383
|
+
]=]
|
|
384
|
+
MetricUnitDefinitions.ROBLOX_METERS_PER_STUD = 0.28
|
|
385
|
+
|
|
386
|
+
-- stylua: ignore
|
|
387
|
+
local SI_PREFIXES: { Prefix } = {
|
|
388
|
+
{ name = "quecto", symbol = "q", factor = 1e-30 }, { name = "ronto", symbol = "r", factor = 1e-27 },
|
|
389
|
+
{ name = "yocto", symbol = "y", factor = 1e-24 }, { name = "zepto", symbol = "z", factor = 1e-21 },
|
|
390
|
+
{ name = "atto", symbol = "a", factor = 1e-18 }, { name = "femto", symbol = "f", factor = 1e-15 },
|
|
391
|
+
{ name = "pico", symbol = "p", factor = 1e-12 }, { name = "nano", symbol = "n", factor = 1e-9 },
|
|
392
|
+
{ name = "micro", symbol = "µ", factor = 1e-6 }, { name = "milli", symbol = "m", factor = 1e-3 },
|
|
393
|
+
{ name = "centi", symbol = "c", factor = 1e-2 }, { name = "deci", symbol = "d", factor = 1e-1 },
|
|
394
|
+
{ name = "deca", symbol = "da", factor = 1e1 }, { name = "hecto", symbol = "h", factor = 1e2 },
|
|
395
|
+
{ name = "kilo", symbol = "k", factor = 1e3 }, { name = "mega", symbol = "M", factor = 1e6 },
|
|
396
|
+
{ name = "giga", symbol = "G", factor = 1e9 }, { name = "tera", symbol = "T", factor = 1e12 },
|
|
397
|
+
{ name = "peta", symbol = "P", factor = 1e15 }, { name = "exa", symbol = "E", factor = 1e18 },
|
|
398
|
+
{ name = "zetta", symbol = "Z", factor = 1e21 }, { name = "yotta", symbol = "Y", factor = 1e24 },
|
|
399
|
+
{ name = "ronna", symbol = "R", factor = 1e27 }, { name = "quetta", symbol = "Q", factor = 1e30 },
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
-- stylua: ignore
|
|
403
|
+
local BINARY_PREFIXES: { Prefix } = {
|
|
404
|
+
{ name = "kibi", symbol = "Ki", factor = 1024 }, { name = "mebi", symbol = "Mi", factor = 1024 ^ 2 },
|
|
405
|
+
{ name = "gibi", symbol = "Gi", factor = 1024 ^ 3 }, { name = "tebi", symbol = "Ti", factor = 1024 ^ 4 },
|
|
406
|
+
{ name = "pebi", symbol = "Pi", factor = 1024 ^ 5 }, { name = "exbi", symbol = "Ei", factor = 1024 ^ 6 },
|
|
407
|
+
{ name = "zebi", symbol = "Zi", factor = 1024 ^ 7 }, { name = "yobi", symbol = "Yi", factor = 1024 ^ 8 },
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
local SI_MULTIPLES: { Prefix } = {}
|
|
411
|
+
for _, prefix in SI_PREFIXES do
|
|
412
|
+
if prefix.factor > 1 then
|
|
413
|
+
table.insert(SI_MULTIPLES, prefix)
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
local SI_MULTIPLES_AND_BINARY: { Prefix } = table.clone(SI_MULTIPLES)
|
|
418
|
+
table.move(BINARY_PREFIXES, 1, #BINARY_PREFIXES, #SI_MULTIPLES_AND_BINARY + 1, SI_MULTIPLES_AND_BINARY)
|
|
419
|
+
|
|
420
|
+
local PREFIX_SETS: { [PrefixSet]: { Prefix } } = {
|
|
421
|
+
si = SI_PREFIXES,
|
|
422
|
+
siMultiples = SI_MULTIPLES,
|
|
423
|
+
siMultiplesAndBinary = SI_MULTIPLES_AND_BINARY,
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
local ALL_PREFIXES: { Prefix } = table.clone(SI_PREFIXES)
|
|
427
|
+
table.move(BINARY_PREFIXES, 1, #BINARY_PREFIXES, #ALL_PREFIXES + 1, ALL_PREFIXES)
|
|
428
|
+
|
|
429
|
+
local QUENTY_TIME_UNIT_ALIASES: { [string]: string } = table.freeze({
|
|
430
|
+
milliseconds = "millisecond",
|
|
431
|
+
ms = "millisecond",
|
|
432
|
+
seconds = "second",
|
|
433
|
+
s = "second",
|
|
434
|
+
minutes = "minute",
|
|
435
|
+
m = "minute",
|
|
436
|
+
hours = "hour",
|
|
437
|
+
h = "hour",
|
|
438
|
+
days = "day",
|
|
439
|
+
d = "day",
|
|
440
|
+
D = "day",
|
|
441
|
+
date = "day",
|
|
442
|
+
weeks = "week",
|
|
443
|
+
w = "week",
|
|
444
|
+
months = "month",
|
|
445
|
+
M = "month",
|
|
446
|
+
quarters = "quarter",
|
|
447
|
+
Q = "quarter",
|
|
448
|
+
years = "year",
|
|
449
|
+
y = "year",
|
|
450
|
+
}) :: any
|
|
451
|
+
|
|
452
|
+
local function toDefinition(kind: MetricUnitKinds.KindName, system: UnitFamily?, row: UnitRow): UnitDefinition
|
|
453
|
+
local dimensions = MetricUnitKinds.fromName(kind)
|
|
454
|
+
local name = row.name
|
|
455
|
+
local short = row.short
|
|
456
|
+
return {
|
|
457
|
+
id = row.id,
|
|
458
|
+
dimensions = dimensions,
|
|
459
|
+
factor = row.factor,
|
|
460
|
+
symbol = row.symbol,
|
|
461
|
+
system = system,
|
|
462
|
+
names = if name then { one = name, other = row.plural or name .. "s" } else nil,
|
|
463
|
+
shortTemplates = if type(short) == "string" then { one = short, other = short } else short,
|
|
464
|
+
aliases = row.aliases,
|
|
465
|
+
zero = row.zero,
|
|
466
|
+
per = row.per,
|
|
467
|
+
duration = if MetricUnitDimensionUtils.equal(dimensions, MetricUnitKinds.TIME) then true else nil,
|
|
468
|
+
}
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
local function withPrefix(prefix: Prefix, word: string, elidesPrefixVowel: boolean?): string
|
|
472
|
+
local lastLetter = string.sub(prefix.name, -1)
|
|
473
|
+
if elidesPrefixVowel and (lastLetter == "a" or lastLetter == "o") then
|
|
474
|
+
return string.sub(prefix.name, 1, -2) .. word
|
|
475
|
+
end
|
|
476
|
+
return prefix.name .. word
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
local function prefixedAliases(prefix: Prefix, base: UnitDefinition): { string }?
|
|
480
|
+
local aliases: { string } = {}
|
|
481
|
+
if prefix.name == "micro" then
|
|
482
|
+
table.insert(aliases, "u" .. base.symbol)
|
|
483
|
+
end
|
|
484
|
+
local baseAliases: { string } = base.aliases or {}
|
|
485
|
+
for _, alias in baseAliases do
|
|
486
|
+
local isWord = string.match(alias, "^%a%a%a+$") ~= nil
|
|
487
|
+
table.insert(aliases, if isWord then prefix.name .. alias else prefix.symbol .. alias)
|
|
488
|
+
end
|
|
489
|
+
return if #aliases > 0 then aliases else nil
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
local function toPrefixedDefinition(prefix: Prefix, base: UnitDefinition, elidesPrefixVowel: boolean?): UnitDefinition
|
|
493
|
+
local names = base.names
|
|
494
|
+
return {
|
|
495
|
+
id = withPrefix(prefix, base.id, elidesPrefixVowel) :: any,
|
|
496
|
+
dimensions = base.dimensions,
|
|
497
|
+
factor = prefix.factor * base.factor,
|
|
498
|
+
symbol = prefix.symbol .. base.symbol,
|
|
499
|
+
system = base.system,
|
|
500
|
+
names = if names
|
|
501
|
+
then {
|
|
502
|
+
one = withPrefix(prefix, names.one, elidesPrefixVowel),
|
|
503
|
+
other = withPrefix(prefix, names.other, elidesPrefixVowel),
|
|
504
|
+
}
|
|
505
|
+
else nil,
|
|
506
|
+
aliases = prefixedAliases(prefix, base),
|
|
507
|
+
prefix = { name = prefix.name, base = base.id },
|
|
508
|
+
}
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
type Define = (kind: MetricUnitKinds.KindName, system: UnitFamily?, rows: { UnitRow }) -> ()
|
|
512
|
+
|
|
513
|
+
local function robloxRows(metersPerStud: number): { { kind: MetricUnitKinds.KindName, row: UnitRow } }
|
|
514
|
+
local waterKilogramsPerCubicMeter = 1_000
|
|
515
|
+
-- stylua: ignore
|
|
516
|
+
return {
|
|
517
|
+
{ kind = "length", row = { id = "stud", factor = metersPerStud, symbol = "stud", name = "stud", short = { one = "%s stud", other = "%s studs" } } },
|
|
518
|
+
{ kind = "mass", row = { id = "robloxMassUnit", factor = metersPerStud ^ 3 * waterKilogramsPerCubicMeter, symbol = "RMU", name = "Roblox mass unit" } },
|
|
519
|
+
{ kind = "speed", row = { id = "studPerSecond", factor = metersPerStud, symbol = "stud/s", name = "stud per second", plural = "studs per second", short = { one = "%s stud/s", other = "%s studs/s" }, aliases = { "studs/s" } } },
|
|
520
|
+
{ kind = "acceleration", row = { id = "studPerSecondSquared", factor = metersPerStud, symbol = "stud/s²", name = "stud per second squared", plural = "studs per second squared", short = { one = "%s stud/s²", other = "%s studs/s²" }, aliases = { "studs/s²", "studs/s2" } } },
|
|
521
|
+
}
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
local DAY = 86_400
|
|
525
|
+
-- Julian year, an elapsed-time average for long-range math; calendar years are @quenty/time's Time.add
|
|
526
|
+
local JULIAN_YEAR = 365.25 * DAY
|
|
527
|
+
local AVERAGE_MONTH = JULIAN_YEAR / 12
|
|
528
|
+
local INCH = 0.0254
|
|
529
|
+
local MILE = 1_609.344
|
|
530
|
+
local FOOT = 12 * INCH
|
|
531
|
+
local US_GALLON = 3.785411784e-3
|
|
532
|
+
local IMPERIAL_GALLON = 4.54609e-3
|
|
533
|
+
local POUND = 0.45359237
|
|
534
|
+
local STANDARD_GRAVITY = 9.80665
|
|
535
|
+
local DEGREE = math.pi / 180
|
|
536
|
+
local REVOLUTION = 2 * math.pi
|
|
537
|
+
local CELSIUS_ZERO = 273.15
|
|
538
|
+
local BIT = 1 / 8
|
|
539
|
+
local POUND_FORCE = POUND * STANDARD_GRAVITY
|
|
540
|
+
|
|
541
|
+
-- stylua: ignore
|
|
542
|
+
local function declareWellKnownUnits(define: Define)
|
|
543
|
+
define("time", nil, {
|
|
544
|
+
{ id = "microsecond", factor = 1e-6, symbol = "µs", name = "microsecond", aliases = { "us" } },
|
|
545
|
+
{ id = "millisecond", factor = 1e-3, symbol = "ms", aliases = { "msec", "msecs" } },
|
|
546
|
+
{ id = "second", factor = 1, symbol = "s", aliases = { "sec", "secs" } },
|
|
547
|
+
{ id = "minute", factor = 60, symbol = "min", aliases = { "mins" } },
|
|
548
|
+
{ id = "hour", factor = 3_600, symbol = "h", aliases = { "hr", "hrs" } },
|
|
549
|
+
{ id = "day", factor = DAY, symbol = "d" },
|
|
550
|
+
{ id = "week", factor = 7 * DAY, symbol = "wk", aliases = { "wks" } },
|
|
551
|
+
{ id = "month", factor = AVERAGE_MONTH, symbol = "mo", aliases = { "mos" } },
|
|
552
|
+
{ id = "quarter", factor = JULIAN_YEAR / 4, symbol = "qtr" },
|
|
553
|
+
{ id = "year", factor = JULIAN_YEAR, symbol = "yr", aliases = { "yrs" } },
|
|
554
|
+
})
|
|
555
|
+
|
|
556
|
+
define("rate", nil, {
|
|
557
|
+
{ id = "perSecond", factor = 1, symbol = "/s", per = "second" },
|
|
558
|
+
{ id = "perMinute", factor = 1 / 60, symbol = "/min", per = "minute" },
|
|
559
|
+
{ id = "perHour", factor = 1 / 3_600, symbol = "/h", per = "hour" },
|
|
560
|
+
{ id = "perDay", factor = 1 / DAY, symbol = "/d", per = "day" },
|
|
561
|
+
{ id = "perWeek", factor = 1 / (7 * DAY), symbol = "/wk", per = "week" },
|
|
562
|
+
{ id = "perMonth", factor = 12 / JULIAN_YEAR, symbol = "/mo", per = "month" },
|
|
563
|
+
{ id = "perYear", factor = 1 / JULIAN_YEAR, symbol = "/yr", per = "year" },
|
|
564
|
+
})
|
|
565
|
+
define("rate", "metric", {
|
|
566
|
+
{ id = "hertz", factor = 1, symbol = "Hz", name = "hertz", plural = "hertz", prefixes = "si" },
|
|
567
|
+
{ id = "becquerel", factor = 1, symbol = "Bq", name = "becquerel", prefixes = "si" },
|
|
568
|
+
})
|
|
569
|
+
|
|
570
|
+
-- Proportions
|
|
571
|
+
define("none", "metric", {
|
|
572
|
+
{ id = "percent", factor = 1e-2, symbol = "%", name = "percent", plural = "percent", short = "%s%", aliases = { "pct" } },
|
|
573
|
+
{ id = "permille", factor = 1e-3, symbol = "‰", name = "per mille", plural = "per mille", short = "%s‰" },
|
|
574
|
+
})
|
|
575
|
+
|
|
576
|
+
define("length", "metric", {
|
|
577
|
+
{ id = "meter", factor = 1, symbol = "m", name = "meter", prefixes = "si" },
|
|
578
|
+
})
|
|
579
|
+
define("length", "usCustomaryAndImperial", {
|
|
580
|
+
{ id = "inch", factor = INCH, symbol = "in", name = "inch", plural = "inches" },
|
|
581
|
+
{ id = "foot", factor = FOOT, symbol = "ft", name = "foot", plural = "feet" },
|
|
582
|
+
{ id = "yard", factor = 3 * FOOT, symbol = "yd", name = "yard" },
|
|
583
|
+
{ id = "mile", factor = MILE, symbol = "mi", name = "mile" },
|
|
584
|
+
{ id = "nauticalMile", factor = 1_852, symbol = "nmi", name = "nautical mile" },
|
|
585
|
+
})
|
|
586
|
+
|
|
587
|
+
define("area", "metric", {
|
|
588
|
+
{ id = "squareMillimeter", factor = 1e-6, symbol = "mm²", name = "square millimeter", aliases = { "mm2" } },
|
|
589
|
+
{ id = "squareCentimeter", factor = 1e-4, symbol = "cm²", name = "square centimeter", aliases = { "cm2" } },
|
|
590
|
+
{ id = "squareMeter", factor = 1, symbol = "m²", name = "square meter", aliases = { "m2", "sq m" } },
|
|
591
|
+
{ id = "hectare", factor = 1e4, symbol = "ha", name = "hectare" },
|
|
592
|
+
{ id = "squareKilometer", factor = 1e6, symbol = "km²", name = "square kilometer", aliases = { "km2", "sq km" } },
|
|
593
|
+
})
|
|
594
|
+
define("area", "metric", {
|
|
595
|
+
{ id = "literPer100Kilometers", factor = 1e-3 / 1e5, symbol = "L/100 km", name = "liter per 100 kilometers", plural = "liters per 100 kilometers", aliases = { "L/100km", "l/100km" } },
|
|
596
|
+
})
|
|
597
|
+
define("area", "usCustomaryAndImperial", {
|
|
598
|
+
{ id = "squareInch", factor = INCH ^ 2, symbol = "in²", name = "square inch", plural = "square inches", aliases = { "in2", "sq in" } },
|
|
599
|
+
{ id = "squareFoot", factor = FOOT ^ 2, symbol = "ft²", name = "square foot", plural = "square feet", aliases = { "ft2", "sq ft" } },
|
|
600
|
+
{ id = "squareYard", factor = (3 * FOOT) ^ 2, symbol = "yd²", name = "square yard", aliases = { "yd2", "sq yd" } },
|
|
601
|
+
{ id = "acre", factor = 4_046.8564224, symbol = "ac", name = "acre" },
|
|
602
|
+
{ id = "squareMile", factor = MILE ^ 2, symbol = "mi²", name = "square mile", aliases = { "mi2", "sq mi" } },
|
|
603
|
+
})
|
|
604
|
+
|
|
605
|
+
define("volume", "metric", {
|
|
606
|
+
{ id = "liter", factor = 1e-3, symbol = "L", name = "liter", aliases = { "l" }, prefixes = "si" },
|
|
607
|
+
{ id = "cubicMeter", factor = 1, symbol = "m³", name = "cubic meter", aliases = { "m3" } },
|
|
608
|
+
})
|
|
609
|
+
define("volume", "usCustomaryAndImperial", {
|
|
610
|
+
{ id = "cubicInch", factor = INCH ^ 3, symbol = "in³", name = "cubic inch", plural = "cubic inches", aliases = { "in3", "cu in" } },
|
|
611
|
+
{ id = "cubicFoot", factor = FOOT ^ 3, symbol = "ft³", name = "cubic foot", plural = "cubic feet", aliases = { "ft3", "cu ft" } },
|
|
612
|
+
{ id = "cubicYard", factor = (3 * FOOT) ^ 3, symbol = "yd³", name = "cubic yard", aliases = { "yd3", "cu yd" } },
|
|
613
|
+
})
|
|
614
|
+
define("volume", "usCustomary", {
|
|
615
|
+
{ id = "usTeaspoon", factor = US_GALLON / 768, symbol = "tsp", name = "teaspoon" },
|
|
616
|
+
{ id = "usTablespoon", factor = US_GALLON / 256, symbol = "tbsp", name = "tablespoon" },
|
|
617
|
+
{ id = "usFluidOunce", factor = US_GALLON / 128, symbol = "US fl oz", name = "US fluid ounce", aliases = { "fl oz" } },
|
|
618
|
+
{ id = "usCup", factor = US_GALLON / 16, symbol = "cup", name = "cup", short = { one = "%s cup", other = "%s cups" } },
|
|
619
|
+
{ id = "usPint", factor = US_GALLON / 8, symbol = "US pt", name = "US pint", aliases = { "pt" } },
|
|
620
|
+
{ id = "usQuart", factor = US_GALLON / 4, symbol = "US qt", name = "US quart", aliases = { "qt" } },
|
|
621
|
+
{ id = "usGallon", factor = US_GALLON, symbol = "US gal", name = "US gallon", aliases = { "gal" } },
|
|
622
|
+
})
|
|
623
|
+
define("volume", "imperial", {
|
|
624
|
+
{ id = "imperialFluidOunce", factor = IMPERIAL_GALLON / 160, symbol = "imp fl oz", name = "imperial fluid ounce" },
|
|
625
|
+
{ id = "imperialPint", factor = IMPERIAL_GALLON / 8, symbol = "imp pt", name = "imperial pint" },
|
|
626
|
+
{ id = "imperialQuart", factor = IMPERIAL_GALLON / 4, symbol = "imp qt", name = "imperial quart" },
|
|
627
|
+
{ id = "imperialGallon", factor = IMPERIAL_GALLON, symbol = "imp gal", name = "imperial gallon" },
|
|
628
|
+
})
|
|
629
|
+
|
|
630
|
+
define("memory", "metric", {
|
|
631
|
+
{ id = "bit", factor = BIT, symbol = "bit", name = "bit", prefixes = "siMultiples" },
|
|
632
|
+
{ id = "byte", factor = 1, symbol = "B", name = "byte", prefixes = "siMultiplesAndBinary" },
|
|
633
|
+
{ id = "kilobyte", factor = 1e3, symbol = "kB", name = "kilobyte", aliases = { "KB" } },
|
|
634
|
+
})
|
|
635
|
+
|
|
636
|
+
define("dataRate", "metric", {
|
|
637
|
+
{ id = "bitPerSecond", factor = BIT, symbol = "bit/s", name = "bit per second", plural = "bits per second", aliases = { "bps" } },
|
|
638
|
+
{ id = "kilobitPerSecond", factor = 1e3 * BIT, symbol = "kbit/s", name = "kilobit per second", plural = "kilobits per second", aliases = { "kbps" } },
|
|
639
|
+
{ id = "megabitPerSecond", factor = 1e6 * BIT, symbol = "Mbit/s", name = "megabit per second", plural = "megabits per second", aliases = { "Mbps" } },
|
|
640
|
+
{ id = "gigabitPerSecond", factor = 1e9 * BIT, symbol = "Gbit/s", name = "gigabit per second", plural = "gigabits per second", aliases = { "Gbps" } },
|
|
641
|
+
{ id = "bytePerSecond", factor = 1, symbol = "B/s", name = "byte per second", plural = "bytes per second" },
|
|
642
|
+
{ id = "kilobytePerSecond", factor = 1e3, symbol = "kB/s", name = "kilobyte per second", plural = "kilobytes per second", aliases = { "KB/s" } },
|
|
643
|
+
})
|
|
644
|
+
|
|
645
|
+
define("mass", "metric", {
|
|
646
|
+
{ id = "gram", factor = 1e-3, symbol = "g", name = "gram", prefixes = "si" },
|
|
647
|
+
{ id = "tonne", factor = 1e3, symbol = "t", name = "metric ton" },
|
|
648
|
+
})
|
|
649
|
+
define("mass", "usCustomaryAndImperial", {
|
|
650
|
+
{ id = "ounce", factor = POUND / 16, symbol = "oz", name = "ounce" },
|
|
651
|
+
{ id = "pound", factor = POUND, symbol = "lb", name = "pound", aliases = { "lbs" } },
|
|
652
|
+
})
|
|
653
|
+
define("mass", "usCustomary", {
|
|
654
|
+
{ id = "shortTon", factor = 2_000 * POUND, symbol = "tn", name = "short ton", aliases = { "ton", "tons" } },
|
|
655
|
+
})
|
|
656
|
+
define("mass", "imperial", {
|
|
657
|
+
{ id = "stone", factor = 14 * POUND, symbol = "st", name = "stone", plural = "stone" },
|
|
658
|
+
})
|
|
659
|
+
|
|
660
|
+
define("speed", "metric", {
|
|
661
|
+
{ id = "meterPerSecond", factor = 1, symbol = "m/s", name = "meter per second", plural = "meters per second" },
|
|
662
|
+
{ id = "kilometerPerHour", factor = 1e3 / 3_600, symbol = "km/h", name = "kilometer per hour", plural = "kilometers per hour", aliases = { "kph", "kmh", "km/hr" } },
|
|
663
|
+
})
|
|
664
|
+
define("speed", "usCustomaryAndImperial", {
|
|
665
|
+
{ id = "milePerHour", factor = MILE / 3_600, symbol = "mph", name = "mile per hour", plural = "miles per hour", aliases = { "mi/h" } },
|
|
666
|
+
{ id = "footPerSecond", factor = FOOT, symbol = "ft/s", name = "foot per second", plural = "feet per second", aliases = { "fps" } },
|
|
667
|
+
{ id = "knot", factor = 1_852 / 3_600, symbol = "kn", name = "knot", aliases = { "kt" } },
|
|
668
|
+
})
|
|
669
|
+
|
|
670
|
+
define("acceleration", "metric", {
|
|
671
|
+
{ id = "meterPerSecondSquared", factor = 1, symbol = "m/s²", name = "meter per second squared", plural = "meters per second squared", aliases = { "m/s2" } },
|
|
672
|
+
})
|
|
673
|
+
define("acceleration", "usCustomaryAndImperial", {
|
|
674
|
+
{ id = "footPerSecondSquared", factor = FOOT, symbol = "ft/s²", name = "foot per second squared", plural = "feet per second squared", aliases = { "ft/s2" } },
|
|
675
|
+
})
|
|
676
|
+
|
|
677
|
+
define("force", "metric", {
|
|
678
|
+
{ id = "newton", factor = 1, symbol = "N", name = "newton", prefixes = "si" },
|
|
679
|
+
})
|
|
680
|
+
define("force", "usCustomaryAndImperial", {
|
|
681
|
+
{ id = "poundForce", factor = POUND_FORCE, symbol = "lbf", name = "pound-force", plural = "pounds-force" },
|
|
682
|
+
})
|
|
683
|
+
|
|
684
|
+
define("energy", "metric", {
|
|
685
|
+
{ id = "joule", factor = 1, symbol = "J", name = "joule", prefixes = "si" },
|
|
686
|
+
{ id = "kilowattHour", factor = 3.6e6, symbol = "kWh", name = "kilowatt-hour" },
|
|
687
|
+
{ id = "kilocalorie", factor = 4_184, symbol = "kcal", name = "kilocalorie" },
|
|
688
|
+
{ id = "newtonMeter", factor = 1, symbol = "N·m", name = "newton-meter", aliases = { "Nm", "N m" } },
|
|
689
|
+
})
|
|
690
|
+
define("energy", "usCustomaryAndImperial", {
|
|
691
|
+
{ id = "britishThermalUnit", factor = 1_055.05585262, symbol = "Btu", name = "British thermal unit", aliases = { "BTU" } },
|
|
692
|
+
{ id = "poundFoot", factor = POUND_FORCE * FOOT, symbol = "lbf·ft", name = "pound-foot", plural = "pound-feet", aliases = { "lb-ft", "lb·ft", "ft-lb", "ft·lbf" } },
|
|
693
|
+
})
|
|
694
|
+
|
|
695
|
+
define("power", "metric", {
|
|
696
|
+
{ id = "watt", factor = 1, symbol = "W", name = "watt", prefixes = "si" },
|
|
697
|
+
{ id = "metricHorsepower", factor = 735.49875, symbol = "PS", name = "metric horsepower", plural = "metric horsepower", aliases = { "CV", "ch" } },
|
|
698
|
+
})
|
|
699
|
+
define("power", "usCustomaryAndImperial", {
|
|
700
|
+
{ id = "horsepower", factor = 550 * POUND_FORCE * FOOT, symbol = "hp", name = "horsepower", plural = "horsepower", aliases = { "bhp" } },
|
|
701
|
+
})
|
|
702
|
+
|
|
703
|
+
define("pressure", "metric", {
|
|
704
|
+
{ id = "pascal", factor = 1, symbol = "Pa", name = "pascal", prefixes = "si" },
|
|
705
|
+
{ id = "bar", factor = 1e5, symbol = "bar", name = "bar" },
|
|
706
|
+
})
|
|
707
|
+
define("pressure", "usCustomaryAndImperial", {
|
|
708
|
+
{ id = "poundForcePerSquareInch", factor = POUND_FORCE / INCH ^ 2, symbol = "psi", name = "pound-force per square inch", plural = "pounds-force per square inch" },
|
|
709
|
+
{ id = "inchOfMercury", factor = 3_386.389, symbol = "inHg", name = "inch of mercury", plural = "inches of mercury" },
|
|
710
|
+
})
|
|
711
|
+
|
|
712
|
+
define("density", "metric", {
|
|
713
|
+
{ id = "kilogramPerCubicMeter", factor = 1, symbol = "kg/m³", name = "kilogram per cubic meter", plural = "kilograms per cubic meter", aliases = { "kg/m3" } },
|
|
714
|
+
{ id = "gramPerCubicCentimeter", factor = 1e3, symbol = "g/cm³", name = "gram per cubic centimeter", plural = "grams per cubic centimeter", aliases = { "g/cm3" } },
|
|
715
|
+
})
|
|
716
|
+
define("density", "usCustomaryAndImperial", {
|
|
717
|
+
{ id = "poundPerCubicFoot", factor = POUND / FOOT ^ 3, symbol = "lb/ft³", name = "pound per cubic foot", plural = "pounds per cubic foot", aliases = { "lb/ft3" } },
|
|
718
|
+
})
|
|
719
|
+
|
|
720
|
+
define("fuelEconomy", "metric", {
|
|
721
|
+
{ id = "kilometerPerLiter", factor = 1e3 / 1e-3, symbol = "km/L", name = "kilometer per liter", plural = "kilometers per liter", aliases = { "kmpl" } },
|
|
722
|
+
})
|
|
723
|
+
define("fuelEconomy", "usCustomary", {
|
|
724
|
+
{ id = "milePerUsGallon", factor = MILE / US_GALLON, symbol = "mpg (US)", name = "mile per US gallon", plural = "miles per US gallon", aliases = { "mpg" } },
|
|
725
|
+
})
|
|
726
|
+
define("fuelEconomy", "imperial", {
|
|
727
|
+
{ id = "milePerImperialGallon", factor = MILE / IMPERIAL_GALLON, symbol = "mpg (UK)", name = "mile per imperial gallon", plural = "miles per imperial gallon", aliases = { "mpg UK", "mpg imp" } },
|
|
728
|
+
})
|
|
729
|
+
|
|
730
|
+
define("temperature", "metric", {
|
|
731
|
+
{ id = "kelvin", factor = 1, symbol = "K", name = "kelvin", zero = 0 },
|
|
732
|
+
{ id = "celsius", factor = 1, symbol = "°C", name = "degree Celsius", plural = "degrees Celsius", aliases = { "C", "degC", "°c" }, zero = CELSIUS_ZERO },
|
|
733
|
+
})
|
|
734
|
+
define("temperature", "usCustomaryAndImperial", {
|
|
735
|
+
{ id = "fahrenheit", factor = 5 / 9, symbol = "°F", name = "degree Fahrenheit", plural = "degrees Fahrenheit", aliases = { "F", "degF", "°f" }, zero = 459.67 * 5 / 9 },
|
|
736
|
+
{ id = "rankine", factor = 5 / 9, symbol = "°R", name = "degree Rankine", plural = "degrees Rankine", zero = 0 },
|
|
737
|
+
})
|
|
738
|
+
|
|
739
|
+
define("angle", "metric", {
|
|
740
|
+
{ id = "radian", factor = 1, symbol = "rad", name = "radian", aliases = { "rads" } },
|
|
741
|
+
{ id = "degree", factor = DEGREE, symbol = "°", name = "degree", short = "%s°", aliases = { "deg", "degs" } },
|
|
742
|
+
{ id = "revolution", factor = REVOLUTION, symbol = "rev", name = "revolution", aliases = { "turn", "turns", "revs" } },
|
|
743
|
+
})
|
|
744
|
+
|
|
745
|
+
define("angularVelocity", "metric", {
|
|
746
|
+
{ id = "radianPerSecond", factor = 1, symbol = "rad/s", name = "radian per second", plural = "radians per second" },
|
|
747
|
+
{ id = "degreePerSecond", factor = DEGREE, symbol = "°/s", name = "degree per second", plural = "degrees per second", aliases = { "deg/s" } },
|
|
748
|
+
{ id = "revolutionPerMinute", factor = REVOLUTION / 60, symbol = "rpm", name = "revolution per minute", plural = "revolutions per minute", aliases = { "RPM", "rev/min" } },
|
|
749
|
+
})
|
|
750
|
+
|
|
751
|
+
define("angularAcceleration", "metric", {
|
|
752
|
+
{ id = "radianPerSecondSquared", factor = 1, symbol = "rad/s²", name = "radian per second squared", plural = "radians per second squared", aliases = { "rad/s2" } },
|
|
753
|
+
})
|
|
754
|
+
|
|
755
|
+
define("current", "metric", {
|
|
756
|
+
{ id = "ampere", factor = 1, symbol = "A", name = "ampere", aliases = { "amp", "amps" }, prefixes = "si" },
|
|
757
|
+
})
|
|
758
|
+
|
|
759
|
+
define("charge", "metric", {
|
|
760
|
+
{ id = "coulomb", factor = 1, symbol = "C", name = "coulomb", prefixes = "si" },
|
|
761
|
+
})
|
|
762
|
+
|
|
763
|
+
define("voltage", "metric", {
|
|
764
|
+
{ id = "volt", factor = 1, symbol = "V", name = "volt", prefixes = "si" },
|
|
765
|
+
})
|
|
766
|
+
|
|
767
|
+
define("resistance", "metric", {
|
|
768
|
+
{ id = "ohm", factor = 1, symbol = "Ω", name = "ohm", prefixes = "si", elidesPrefixVowel = true },
|
|
769
|
+
})
|
|
770
|
+
|
|
771
|
+
define("conductance", "metric", {
|
|
772
|
+
{ id = "siemens", factor = 1, symbol = "S", name = "siemens", plural = "siemens", prefixes = "si" },
|
|
773
|
+
})
|
|
774
|
+
|
|
775
|
+
define("capacitance", "metric", {
|
|
776
|
+
{ id = "farad", factor = 1, symbol = "F", name = "farad", prefixes = "si" },
|
|
777
|
+
})
|
|
778
|
+
|
|
779
|
+
define("inductance", "metric", {
|
|
780
|
+
{ id = "henry", factor = 1, symbol = "H", name = "henry", plural = "henries", prefixes = "si" },
|
|
781
|
+
})
|
|
782
|
+
|
|
783
|
+
define("magneticFlux", "metric", {
|
|
784
|
+
{ id = "weber", factor = 1, symbol = "Wb", name = "weber", prefixes = "si" },
|
|
785
|
+
})
|
|
786
|
+
|
|
787
|
+
define("amount", "metric", {
|
|
788
|
+
{ id = "mole", factor = 1, symbol = "mol", name = "mole", prefixes = "si" },
|
|
789
|
+
})
|
|
790
|
+
define("molarMass", "metric", {
|
|
791
|
+
{ id = "gramPerMole", factor = 1e-3, symbol = "g/mol", name = "gram per mole", plural = "grams per mole" },
|
|
792
|
+
})
|
|
793
|
+
define("molarConcentration", "metric", {
|
|
794
|
+
{ id = "molePerLiter", factor = 1e3, symbol = "mol/L", name = "mole per liter", plural = "moles per liter" },
|
|
795
|
+
{ id = "millimolePerLiter", factor = 1, symbol = "mmol/L", name = "millimole per liter", plural = "millimoles per liter" },
|
|
796
|
+
})
|
|
797
|
+
define("catalyticActivity", "metric", {
|
|
798
|
+
{ id = "katal", factor = 1, symbol = "kat", name = "katal", prefixes = "si" },
|
|
799
|
+
})
|
|
800
|
+
|
|
801
|
+
define("luminousIntensity", "metric", {
|
|
802
|
+
{ id = "candela", factor = 1, symbol = "cd", name = "candela", prefixes = "si" },
|
|
803
|
+
})
|
|
804
|
+
define("solidAngle", "metric", {
|
|
805
|
+
{ id = "steradian", factor = 1, symbol = "sr", name = "steradian" },
|
|
806
|
+
})
|
|
807
|
+
define("luminousFlux", "metric", {
|
|
808
|
+
{ id = "lumen", factor = 1, symbol = "lm", name = "lumen", prefixes = "si" },
|
|
809
|
+
})
|
|
810
|
+
define("illuminance", "metric", {
|
|
811
|
+
{ id = "lux", factor = 1, symbol = "lx", name = "lux", plural = "lux", prefixes = "si" },
|
|
812
|
+
})
|
|
813
|
+
|
|
814
|
+
define("absorbedDose", "metric", {
|
|
815
|
+
{ id = "gray", factor = 1, symbol = "Gy", name = "gray", prefixes = "si" },
|
|
816
|
+
{ id = "sievert", factor = 1, symbol = "Sv", name = "sievert", prefixes = "si" },
|
|
817
|
+
})
|
|
818
|
+
|
|
819
|
+
for _, robloxRow in robloxRows(MetricUnitDefinitions.ROBLOX_METERS_PER_STUD) do
|
|
820
|
+
define(robloxRow.kind, "roblox", { robloxRow.row })
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
define("magneticFluxDensity", "metric", {
|
|
824
|
+
{ id = "tesla", factor = 1, symbol = "T", name = "tesla", prefixes = "si" },
|
|
825
|
+
})
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
type Prefixing = { prefixes: { Prefix }, elidesPrefixVowel: boolean? }
|
|
829
|
+
|
|
830
|
+
type Registry = {
|
|
831
|
+
declared: { UnitDefinition },
|
|
832
|
+
byId: { [string]: UnitDefinition },
|
|
833
|
+
prefixingByBaseId: { [string]: Prefixing },
|
|
834
|
+
prefixableInOrder: { UnitDefinition },
|
|
835
|
+
everyUnit: { UnitDefinition }?,
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
local registry: Registry? = nil
|
|
839
|
+
|
|
840
|
+
local function getRegistry(): Registry
|
|
841
|
+
local found = registry
|
|
842
|
+
if found then
|
|
843
|
+
return found
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
local declared: { UnitDefinition } = {}
|
|
847
|
+
local byId: { [string]: UnitDefinition } = {}
|
|
848
|
+
local prefixingByBaseId: { [string]: Prefixing } = {}
|
|
849
|
+
local prefixableInOrder: { UnitDefinition } = {}
|
|
850
|
+
declareWellKnownUnits(function(kind: MetricUnitKinds.KindName, system: UnitFamily?, rows: { UnitRow })
|
|
851
|
+
for _, row in rows do
|
|
852
|
+
local unit = table.freeze(toDefinition(kind, system, row))
|
|
853
|
+
assert(byId[unit.id] == nil, string.format("Unit %q is declared twice", unit.id))
|
|
854
|
+
table.insert(declared, unit)
|
|
855
|
+
byId[unit.id] = unit
|
|
856
|
+
local prefixSet = row.prefixes
|
|
857
|
+
if prefixSet then
|
|
858
|
+
prefixingByBaseId[unit.id] =
|
|
859
|
+
{ prefixes = PREFIX_SETS[prefixSet :: PrefixSet], elidesPrefixVowel = row.elidesPrefixVowel }
|
|
860
|
+
table.insert(prefixableInOrder, unit)
|
|
861
|
+
end
|
|
862
|
+
end
|
|
863
|
+
end)
|
|
864
|
+
|
|
865
|
+
local built: Registry = {
|
|
866
|
+
declared = table.freeze(declared),
|
|
867
|
+
byId = byId,
|
|
868
|
+
prefixingByBaseId = prefixingByBaseId,
|
|
869
|
+
prefixableInOrder = prefixableInOrder,
|
|
870
|
+
everyUnit = nil,
|
|
871
|
+
}
|
|
872
|
+
registry = built
|
|
873
|
+
return built
|
|
874
|
+
end
|
|
875
|
+
|
|
876
|
+
local function findPrefixedUnitById(id: string): UnitDefinition?
|
|
877
|
+
local byId = getRegistry().byId
|
|
878
|
+
for _, prefix in ALL_PREFIXES do
|
|
879
|
+
for _, prefixText in { prefix.name, string.sub(prefix.name, 1, -2) } do
|
|
880
|
+
local base = if string.sub(id, 1, #prefixText) == prefixText
|
|
881
|
+
then byId[string.sub(id, #prefixText + 1)]
|
|
882
|
+
else nil
|
|
883
|
+
local unit = if base then MetricUnitDefinitions.getPrefixedUnit(prefix, base) else nil
|
|
884
|
+
if unit and unit.id == id then
|
|
885
|
+
return unit
|
|
886
|
+
end
|
|
887
|
+
end
|
|
888
|
+
end
|
|
889
|
+
return nil
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
--[=[
|
|
893
|
+
The unit named `unit`, or nil. Takes any [UnitLike], so `"hours"` and `"h"` find `"hour"`, and a unit is
|
|
894
|
+
returned as it is.
|
|
895
|
+
|
|
896
|
+
@param unit UnitLike
|
|
897
|
+
@return UnitDefinition?
|
|
898
|
+
]=]
|
|
899
|
+
function MetricUnitDefinitions.getUnit(unit: string | UnitDefinition): UnitDefinition?
|
|
900
|
+
if type(unit) == "table" then
|
|
901
|
+
return if MetricUnitDefinitions.isUnitDefinition(unit) then unit :: UnitDefinition else nil
|
|
902
|
+
end
|
|
903
|
+
local byId = getRegistry().byId
|
|
904
|
+
return byId[unit] or byId[QUENTY_TIME_UNIT_ALIASES[unit] or ""] or findPrefixedUnitById(unit)
|
|
905
|
+
end
|
|
906
|
+
|
|
907
|
+
--[=[
|
|
908
|
+
The unit `prefix` makes of `base`, such as `kilometer` for `kilo` and `meter`, or nil when `base` does not take
|
|
909
|
+
that prefix.
|
|
910
|
+
|
|
911
|
+
@param prefix Prefix
|
|
912
|
+
@param base UnitDefinition
|
|
913
|
+
@return UnitDefinition?
|
|
914
|
+
]=]
|
|
915
|
+
function MetricUnitDefinitions.getPrefixedUnit(prefix: Prefix, base: UnitDefinition): UnitDefinition?
|
|
916
|
+
local found = getRegistry()
|
|
917
|
+
local prefixing = found.prefixingByBaseId[base.id]
|
|
918
|
+
if not (prefixing and table.find(prefixing.prefixes, prefix)) then
|
|
919
|
+
return nil
|
|
920
|
+
end
|
|
921
|
+
local id = withPrefix(prefix, base.id, prefixing.elidesPrefixVowel)
|
|
922
|
+
local existing = found.byId[id]
|
|
923
|
+
if existing then
|
|
924
|
+
return existing
|
|
925
|
+
end
|
|
926
|
+
local unit = table.freeze(toPrefixedDefinition(prefix, base, prefixing.elidesPrefixVowel))
|
|
927
|
+
found.byId[id] = unit
|
|
928
|
+
return unit
|
|
929
|
+
end
|
|
930
|
+
|
|
931
|
+
--[=[
|
|
932
|
+
The units declared outright, without their prefixed forms, in the order declared. Cheaper than
|
|
933
|
+
[MetricUnitDefinitions.getUnits]; [MetricUnitDefinitions.getPrefixedUnit] finds the rest.
|
|
934
|
+
|
|
935
|
+
@return { UnitDefinition }
|
|
936
|
+
]=]
|
|
937
|
+
function MetricUnitDefinitions.getDeclaredUnits(): { UnitDefinition }
|
|
938
|
+
return getRegistry().declared
|
|
939
|
+
end
|
|
940
|
+
|
|
941
|
+
--[=[
|
|
942
|
+
Every unit, in the order declared, then every prefixed form. Building the prefixed forms costs a few
|
|
943
|
+
milliseconds the first time, so look units up with [MetricUnitDefinitions.getUnit] where you can.
|
|
944
|
+
|
|
945
|
+
@return { UnitDefinition }
|
|
946
|
+
]=]
|
|
947
|
+
function MetricUnitDefinitions.getUnits(): { UnitDefinition }
|
|
948
|
+
local found = getRegistry()
|
|
949
|
+
local everyUnit = found.everyUnit
|
|
950
|
+
if everyUnit then
|
|
951
|
+
return everyUnit
|
|
952
|
+
end
|
|
953
|
+
local units = table.clone(found.declared)
|
|
954
|
+
for _, base in found.prefixableInOrder do
|
|
955
|
+
for _, prefix in found.prefixingByBaseId[base.id].prefixes do
|
|
956
|
+
local unit = MetricUnitDefinitions.getPrefixedUnit(prefix, base)
|
|
957
|
+
local isDeclaredOutright = unit ~= nil and unit.prefix == nil
|
|
958
|
+
if unit and not isDeclaredOutright then
|
|
959
|
+
table.insert(units, unit)
|
|
960
|
+
end
|
|
961
|
+
end
|
|
962
|
+
end
|
|
963
|
+
local frozen = table.freeze(units)
|
|
964
|
+
found.everyUnit = frozen
|
|
965
|
+
return frozen
|
|
966
|
+
end
|
|
967
|
+
|
|
968
|
+
--[=[
|
|
969
|
+
The ids of every unit of `dimensions`, in the order declared.
|
|
970
|
+
|
|
971
|
+
@param dimensions Dimensions
|
|
972
|
+
@return { UnitId }
|
|
973
|
+
]=]
|
|
974
|
+
function MetricUnitDefinitions.getUnitIds(dimensions: MetricUnitDimensionUtils.Dimensions): { UnitId }
|
|
975
|
+
local found: { UnitId } = {}
|
|
976
|
+
for _, unit in MetricUnitDefinitions.getUnits() do
|
|
977
|
+
if MetricUnitDimensionUtils.equal(unit.dimensions, dimensions) then
|
|
978
|
+
table.insert(found, unit.id)
|
|
979
|
+
end
|
|
980
|
+
end
|
|
981
|
+
return found
|
|
982
|
+
end
|
|
983
|
+
|
|
984
|
+
--[=[
|
|
985
|
+
Every prefix a unit can take: the twenty-four SI prefixes, smallest first, then the binary ones.
|
|
986
|
+
|
|
987
|
+
@return { Prefix }
|
|
988
|
+
]=]
|
|
989
|
+
function MetricUnitDefinitions.getPrefixes(): { Prefix }
|
|
990
|
+
return ALL_PREFIXES
|
|
991
|
+
end
|
|
992
|
+
|
|
993
|
+
--[=[
|
|
994
|
+
`@quenty/time`'s other names for its time units, such as `"h"` for `"hour"`, mapped to unit ids.
|
|
995
|
+
|
|
996
|
+
@return { [string]: UnitId }
|
|
997
|
+
]=]
|
|
998
|
+
function MetricUnitDefinitions.getTimeAliases(): { [string]: UnitId }
|
|
999
|
+
return QUENTY_TIME_UNIT_ALIASES :: any
|
|
1000
|
+
end
|
|
1001
|
+
|
|
1002
|
+
--[=[
|
|
1003
|
+
Whether `value` is a [UnitDefinition], such as one [MetricUnitSystem.GetUnit] returns.
|
|
1004
|
+
|
|
1005
|
+
@param value any
|
|
1006
|
+
@return boolean
|
|
1007
|
+
]=]
|
|
1008
|
+
function MetricUnitDefinitions.isUnitDefinition(value: any): boolean
|
|
1009
|
+
return type(value) == "table"
|
|
1010
|
+
and type(value.id) == "string"
|
|
1011
|
+
and type(value.factor) == "number"
|
|
1012
|
+
and type(value.symbol) == "string"
|
|
1013
|
+
and MetricUnitDimensionUtils.isDimensions(value.dimensions)
|
|
1014
|
+
end
|
|
1015
|
+
|
|
1016
|
+
--[=[
|
|
1017
|
+
Units for a [MetricUnitSystem] of a game's own, from rows of one kind as in [UnitRow], with their prefixed forms.
|
|
1018
|
+
They are not added to the well-known units; only a system holding them knows them.
|
|
1019
|
+
|
|
1020
|
+
```lua
|
|
1021
|
+
local units = MetricUnitDefinitions.createUnits("length", "space", {
|
|
1022
|
+
{ id = "lightYear", factor = 9.4607e15, symbol = "ly", name = "light-year" },
|
|
1023
|
+
})
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
@param kind KindName
|
|
1027
|
+
@param system string -- the name of the system that declares them
|
|
1028
|
+
@param rows { UnitRow }
|
|
1029
|
+
@return { UnitDefinition }
|
|
1030
|
+
]=]
|
|
1031
|
+
function MetricUnitDefinitions.createUnits(
|
|
1032
|
+
kind: MetricUnitKinds.KindName,
|
|
1033
|
+
system: string,
|
|
1034
|
+
rows: { UnitRow }
|
|
1035
|
+
): { UnitDefinition }
|
|
1036
|
+
local definitions: { UnitDefinition } = {}
|
|
1037
|
+
local prefixables: { { base: UnitDefinition, row: UnitRow } } = {}
|
|
1038
|
+
for _, row in rows do
|
|
1039
|
+
local definition = toDefinition(kind, system, row)
|
|
1040
|
+
table.insert(definitions, definition)
|
|
1041
|
+
if row.prefixes then
|
|
1042
|
+
table.insert(prefixables, { base = definition, row = row })
|
|
1043
|
+
end
|
|
1044
|
+
end
|
|
1045
|
+
local declaredIds: { [string]: true } = {}
|
|
1046
|
+
for _, definition in definitions do
|
|
1047
|
+
declaredIds[definition.id] = true
|
|
1048
|
+
end
|
|
1049
|
+
for _, prefixable in prefixables do
|
|
1050
|
+
for _, prefix in PREFIX_SETS[prefixable.row.prefixes :: PrefixSet] do
|
|
1051
|
+
local unit = toPrefixedDefinition(prefix, prefixable.base, prefixable.row.elidesPrefixVowel)
|
|
1052
|
+
if not declaredIds[unit.id] then
|
|
1053
|
+
table.insert(definitions, unit)
|
|
1054
|
+
end
|
|
1055
|
+
end
|
|
1056
|
+
end
|
|
1057
|
+
for index, definition in definitions do
|
|
1058
|
+
definitions[index] = table.freeze(definition)
|
|
1059
|
+
end
|
|
1060
|
+
return table.freeze(definitions)
|
|
1061
|
+
end
|
|
1062
|
+
|
|
1063
|
+
--[=[
|
|
1064
|
+
The Roblox units at a stud of `metersPerStud`: `stud`, `studPerSecond`, `studPerSecondSquared` and
|
|
1065
|
+
`robloxMassUnit`, a cubic stud of water, so it scales with the cube of the stud.
|
|
1066
|
+
|
|
1067
|
+
@param system string -- the name of the system that declares them
|
|
1068
|
+
@param metersPerStud number
|
|
1069
|
+
@return { UnitDefinition }
|
|
1070
|
+
]=]
|
|
1071
|
+
function MetricUnitDefinitions.createRobloxUnits(system: string, metersPerStud: number): { UnitDefinition }
|
|
1072
|
+
assert(type(metersPerStud) == "number" and metersPerStud > 0, "Bad metersPerStud")
|
|
1073
|
+
local definitions: { UnitDefinition } = {}
|
|
1074
|
+
for _, robloxRow in robloxRows(metersPerStud) do
|
|
1075
|
+
for _, definition in MetricUnitDefinitions.createUnits(robloxRow.kind, system, { robloxRow.row }) do
|
|
1076
|
+
table.insert(definitions, definition)
|
|
1077
|
+
end
|
|
1078
|
+
end
|
|
1079
|
+
return table.freeze(definitions)
|
|
1080
|
+
end
|
|
1081
|
+
|
|
1082
|
+
return table.freeze(MetricUnitDefinitions)
|