Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
ac06a5b
Setup NumberWithUnitsParser and its test file
theMr17 Dec 9, 2025
eb77a64
Parse prefix (front) currency units
theMr17 Dec 10, 2025
1452ccb
Merge remote-tracking branch 'upstream/number-with-units-parser' into…
theMr17 Mar 6, 2026
7e0586c
Setup NumberWithUnitsTokenizer and its test file
theMr17 Mar 6, 2026
ee46270
Add dummy test
theMr17 Mar 6, 2026
d32b666
Define tokens
theMr17 Mar 6, 2026
5623400
Parse PositiveInteger, PositiveRealNumber & MinusSymbol tokens
theMr17 Mar 6, 2026
7d97337
Tokenize fractional numbers
theMr17 Mar 6, 2026
42b5721
Tokenize currency units
theMr17 Mar 7, 2026
1e04a7c
Fix code formatting
theMr17 Mar 7, 2026
564bc21
Tokenize length units
theMr17 Mar 9, 2026
754d036
Tokenize mass units
theMr17 Mar 9, 2026
3af36fb
Tokenize area units
theMr17 Mar 9, 2026
2f973d8
Tokenize volume units
theMr17 Mar 9, 2026
51517a9
Tokenize temperature units
theMr17 Mar 9, 2026
7461692
Fix ktlint issue
theMr17 Mar 9, 2026
3e4820d
Tokenize angle units
theMr17 Mar 9, 2026
0c21ea9
Tokenize time units
theMr17 Mar 9, 2026
b042bbd
Tokenize frequency units
theMr17 Mar 9, 2026
ab942e4
Tokenize amount of substance units
theMr17 Mar 9, 2026
3a18770
Tokenize luminous intensity units
theMr17 Mar 9, 2026
ba64ef6
Tokenize force units
theMr17 Mar 9, 2026
6623eec
Fix ktlint issue
theMr17 Mar 9, 2026
9019edb
Tokenize energy units
theMr17 Mar 9, 2026
f671f47
Tokenize power units
theMr17 Mar 10, 2026
37b0145
Tokenize pressure units
theMr17 Mar 10, 2026
3f75ff3
Tokenize electricity units
theMr17 Mar 10, 2026
c9cd12c
Tokenize SI prefixes
theMr17 Mar 10, 2026
89198cb
Fix ktlint issues
theMr17 Mar 10, 2026
6670c53
Add tests for complex units
theMr17 Mar 10, 2026
90bde56
Add kdocs
theMr17 Mar 10, 2026
778941d
Implement NumberWithUnitsParser
theMr17 Mar 11, 2026
965b927
Add todo NumberWithUnitsTokenSubject's test
theMr17 Mar 11, 2026
17475ca
Fix file name
theMr17 Mar 11, 2026
cf12edc
Fix bazel lint issue
theMr17 Mar 11, 2026
11a1b92
Introduce a NumberWithUnitsSubject
theMr17 Mar 11, 2026
c677557
Add parser tests
theMr17 Mar 11, 2026
644c645
Add todo for NumberWithUnitsParsingError's tests
theMr17 Mar 11, 2026
e02c857
Remove typecast suppression
theMr17 Mar 13, 2026
56e775a
Fix static checks
theMr17 Mar 13, 2026
045981c
Add todo issue number
theMr17 Mar 13, 2026
ffdbbfa
Address review comments
theMr17 Mar 23, 2026
528cabd
Address review comments
theMr17 Mar 23, 2026
3f935dc
Add NumberWithUnitsExpression and related messages for unit represent…
theMr17 Apr 3, 2026
b83e111
Refactor NumberWithUnitsTokenizer to use a generic Unit token
theMr17 Apr 3, 2026
4e91f48
Remove prefix unit tokens
theMr17 Apr 3, 2026
1c27892
Refactor the NumberWithUnitsParser
theMr17 Apr 5, 2026
7726614
Fix ktlint issues
theMr17 Apr 5, 2026
2e0ed28
Introduce map and flatmap
theMr17 Apr 17, 2026
8719340
Address review comment
theMr17 Apr 17, 2026
d20354a
Fix lint issues
theMr17 Apr 17, 2026
bb9ef14
Fix kdoc formatting
theMr17 Apr 17, 2026
1fb2c59
Address review comment
theMr17 Apr 17, 2026
652151b
Address review comments
theMr17 Apr 18, 2026
3fd7cad
Create extension functions
theMr17 Apr 18, 2026
0bc1400
Update parseNumber function
theMr17 Apr 18, 2026
5fdfe3b
Update tokenizer and parser
theMr17 Apr 24, 2026
b2e479e
Add InvalidUnitError class
theMr17 Apr 24, 2026
39d6a41
Fix ktlint issue
theMr17 Apr 24, 2026
6e47b04
Update parseSuffixUnit to use map function
theMr17 Apr 24, 2026
c5bd40b
Fix tokenizer tests
theMr17 Apr 30, 2026
15e202a
Fix static checks
theMr17 Apr 30, 2026
d5930d2
Remove unnecessary blank lines in NumberWithUnitsTokenizerTest
theMr17 Apr 30, 2026
1af2bda
Address review comments
theMr17 Apr 30, 2026
c8dfae1
Introduce a character set constant
theMr17 May 1, 2026
6ddd649
Handle consecutive units without spaces
theMr17 May 5, 2026
7be78dd
Refactor with "...WhoseValue()"
theMr17 May 21, 2026
167fc89
Return a string subject
theMr17 May 21, 2026
7f02cc1
Remove comment
theMr17 May 26, 2026
d21d3c3
Import the error classes directly
theMr17 May 26, 2026
9fd56b8
Use expected variable instead of asserting on the input
theMr17 May 27, 2026
d780487
Updated all the test names to parsesCorrectly instead of parsesInvali…
theMr17 May 27, 2026
f5b44e8
Fix incorrect test names
theMr17 May 27, 2026
07cb7e6
Simplify equality assertions in NumberWithUnitsParserTest using LiteP…
theMr17 Jul 2, 2026
e3d2a16
Replace exact double assertions with precision-based checks in number…
theMr17 Jul 2, 2026
1089bec
Fix test names
theMr17 Jul 11, 2026
a83299b
Update parser to correctly apply exponents to the final unit of decom…
theMr17 Jul 16, 2026
8f8e02a
Make NumberWithUnitsTokenSubject constructor private
theMr17 Jul 16, 2026
26ee50e
Handle bare minus signs and improve error reporting in NumberWithUnit…
theMr17 Jul 17, 2026
79a1c8e
Ensure compound unit decomposition only proceeds when single-unit par…
theMr17 Jul 17, 2026
aa61e3c
Update NumberWithUnitsTokenizer documentation to clarify the separati…
theMr17 Jul 17, 2026
a70da0c
Remove unused expectNextCharsForUnit helper method in NumberWithUnits…
theMr17 Jul 17, 2026
88d6c75
Fix ktlint issue
theMr17 Jul 17, 2026
dc26ae2
Migrate NumberWithUnitsParserTest to use OppiaParameterizedTestRunner…
theMr17 Jul 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions model/src/main/proto/interaction_object.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,162 @@ message NumberUnit {
int32 exponent = 2;
}

// Represents a number with explicitly-defined units.
message NumberWithUnitsExpression {
// The different types of numeric values that can have units.
oneof number_type {
// Indicates the value is a real number (decimal or integer).
double real = 1;

// Indicates the value is a fraction.
Fraction fraction = 2;
}

// Explicitly captures where units appear relative to the numeric value.
// This ensures parser output preserves format-specific semantics.
oneof expression_format {
// Units precede the value.
PrefixValueExpression prefix_value_expression = 3;

// Units follow the value.
ValueSuffixExpression value_suffix_expression = 4;

// Units appear on both sides of the value.
PrefixValueSuffixExpression prefix_value_suffix_expression = 5;
}
}

// Represents expressions where units appear before the number.
message PrefixValueExpression {
repeated NumberUnitExpression prefix_units = 1;
}

// Represents expressions where units appear after the number.
message ValueSuffixExpression {
repeated NumberUnitExpression suffix_units = 1;
}

// Represents expressions where units appear both before and after the number.
message PrefixValueSuffixExpression {
repeated NumberUnitExpression prefix_units = 1;
repeated NumberUnitExpression suffix_units = 2;
}

// Represents a specific unit with an exponent.
message NumberUnitExpression {
// Supported SI prefixes.
// These are combined with [unit].
enum SiPrefix {
SI_PREFIX_UNSPECIFIED = 0;
DECA = 1;
HECTO = 2;
KILO = 3;
MEGA = 4;
GIGA = 5;
TERA = 6;
PETA = 7;
EXA = 8;
ZETTA = 9;
YOTTA = 10;
DECI = 11;
CENTI = 12;
MILLI = 13;
MICRO = 14;
NANO = 15;
PICO = 16;
FEMTO = 17;
ATTO = 18;
ZEPTO = 19;
YOCTO = 20;
}

// The supported base unit types. Prefixed combinations are intentionally not enumerated here.
enum Unit {
UNIT_UNSPECIFIED = 0;

// Length units
METER = 1;
INCH = 2;
FOOT = 3;
YARD = 4;

// Mass units
GRAM = 5;
GRAIN = 6;
OUNCE = 7;

// Area units
SQUARE_METER = 8;
SQUARE_INCH = 9;
SQUARE_FOOT = 10;
SQUARE_YARD = 11;

// Volume unit
CUBIC_METER = 12;
LITER = 13;
CUBIC_CENTIMETER = 14;
CUBIC_INCH = 15;
CUBIC_FOOT = 16;
CUBIC_YARD = 17;

// Temperature units
KELVIN = 18;
CELSIUS = 19;

// Angle units
RADIAN = 20;
DEGREE = 21;

// Time units
SECOND = 22;
MINUTE = 23;
HOUR = 24;

// Frequency units
HERTZ = 25;

// Amount of substance
MOLE = 26;

// Luminous intensity
CANDELA = 27;

// Force
NEWTON = 28;

// Energy
JOULE = 29;

// Power
WATT = 30;

// Pressure
PASCAL = 31;

// Electricity
AMPERE = 32;
VOLT = 33;
OHM = 34;

// Currency units
DOLLAR = 35;
CENT = 36;
RUPEE = 37;
PAISA = 38;
}

// The specific unit value.
Unit unit = 1;

// The exponent (power) of this unit in the expression.
// Positive values indicate numerator units, negative values indicate denominator units.
int32 exponent = 2;

// Optional SI prefix used with [unit].
// Leave as SI_PREFIX_UNSPECIFIED for units that do not have a prefix.
SiPrefix si_prefix = 3;
}

// Structure for a ListOfString object.
message ListOfSetsOfHtmlStrings {
repeated StringList set_of_html_strings = 1;
Expand Down
1 change: 1 addition & 0 deletions scripts/assets/file_content_validation_checks.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ file_content_checks {
exempted_file_name: "utility/src/test/java/org/oppia/android/util/math/MathExpressionExtensionsTest.kt"
exempted_file_name: "utility/src/test/java/org/oppia/android/util/math/MathExpressionParserTest.kt"
exempted_file_name: "utility/src/test/java/org/oppia/android/util/math/MathTokenizerTest.kt"
exempted_file_name: "utility/src/test/java/org/oppia/android/util/math/NumberWithUnitsTokenizerTest.kt"
exempted_file_name: "utility/src/test/java/org/oppia/android/util/math/PolynomialExtensionsTest.kt"
exempted_file_name: "utility/src/test/java/org/oppia/android/util/math/RealExtensionsTest.kt"
exempted_file_name: "utility/src/test/java/org/oppia/android/util/profile/ProfileNameValidatorTest.kt"
Expand Down
12 changes: 12 additions & 0 deletions scripts/assets/test_file_exemptions.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -4351,6 +4351,14 @@ test_file_exemption {
exempted_file_path: "testing/src/main/java/org/oppia/android/testing/logging/SyncStatusTestModule.kt"
override_min_coverage_percent_required: 0
}
test_file_exemption {
exempted_file_path: "testing/src/main/java/org/oppia/android/testing/math/NumberWithUnitsSubject.kt"
test_file_not_required: true
}
test_file_exemption {
exempted_file_path: "testing/src/main/java/org/oppia/android/testing/math/NumberWithUnitsTokenSubject.kt"
test_file_not_required: true
}
test_file_exemption {
exempted_file_path: "testing/src/main/java/org/oppia/android/testing/mockito/MockitoKotlinHelper.kt"
test_file_not_required: true
Expand Down Expand Up @@ -4647,6 +4655,10 @@ test_file_exemption {
exempted_file_path: "utility/src/main/java/org/oppia/android/util/math/MathParsingError.kt"
test_file_not_required: true
}
test_file_exemption {
exempted_file_path: "utility/src/main/java/org/oppia/android/util/math/NumberWithUnitsParsingError.kt"
test_file_not_required: true
}
test_file_exemption {
exempted_file_path: "utility/src/main/java/org/oppia/android/util/networking/ConnectionStatus.kt"
test_file_not_required: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,35 @@ kt_android_library(
"//utility/src/main/java/org/oppia/android/util/math:tokenizer",
],
)

kt_android_library(
name = "number_with_units_subject",
testonly = True,
srcs = [
"NumberWithUnitsSubject.kt",
],
visibility = [
"//:oppia_testing_visibility",
],
deps = [
":fraction_subject",
"//model/src/main/proto:interaction_object_java_proto_lite",
"//third_party:com_google_truth_extensions_truth-liteproto-extension",
"//third_party:com_google_truth_truth",
],
)

kt_android_library(
name = "number_with_units_token_subject",
testonly = True,
srcs = [
"NumberWithUnitsTokenSubject.kt",
],
visibility = [
"//:oppia_testing_visibility",
],
deps = [
"//third_party:com_google_truth_truth",
"//utility/src/main/java/org/oppia/android/util/math:number_with_units_tokenizer",
],
)
Loading
Loading