unitsdb 2.1.1 → 2.2.1

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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +8 -1
  3. data/.gitignore +2 -0
  4. data/.gitmodules +4 -3
  5. data/.rubocop.yml +13 -8
  6. data/.rubocop_todo.yml +217 -100
  7. data/CLAUDE.md +55 -0
  8. data/Gemfile +4 -1
  9. data/README.adoc +283 -16
  10. data/data/dimensions.yaml +1864 -0
  11. data/data/prefixes.yaml +874 -0
  12. data/data/quantities.yaml +3715 -0
  13. data/data/scales.yaml +97 -0
  14. data/data/schemas/dimensions-schema.yaml +153 -0
  15. data/data/schemas/prefixes-schema.yaml +155 -0
  16. data/data/schemas/quantities-schema.yaml +117 -0
  17. data/data/schemas/scales-schema.yaml +106 -0
  18. data/data/schemas/unit_systems-schema.yaml +116 -0
  19. data/data/schemas/units-schema.yaml +215 -0
  20. data/data/unit_systems.yaml +78 -0
  21. data/data/units.yaml +14052 -0
  22. data/exe/unitsdb +7 -1
  23. data/lib/unitsdb/cli.rb +42 -15
  24. data/lib/unitsdb/commands/_modify.rb +40 -4
  25. data/lib/unitsdb/commands/base.rb +6 -2
  26. data/lib/unitsdb/commands/check_si/si_formatter.rb +488 -0
  27. data/lib/unitsdb/commands/check_si/si_matcher.rb +487 -0
  28. data/lib/unitsdb/commands/check_si/si_ttl_parser.rb +103 -0
  29. data/lib/unitsdb/commands/check_si/si_updater.rb +254 -0
  30. data/lib/unitsdb/commands/check_si.rb +54 -35
  31. data/lib/unitsdb/commands/get.rb +11 -10
  32. data/lib/unitsdb/commands/normalize.rb +21 -7
  33. data/lib/unitsdb/commands/qudt/check.rb +150 -0
  34. data/lib/unitsdb/commands/qudt/formatter.rb +194 -0
  35. data/lib/unitsdb/commands/qudt/matcher.rb +746 -0
  36. data/lib/unitsdb/commands/qudt/ttl_parser.rb +403 -0
  37. data/lib/unitsdb/commands/qudt/update.rb +126 -0
  38. data/lib/unitsdb/commands/qudt/updater.rb +189 -0
  39. data/lib/unitsdb/commands/qudt.rb +82 -0
  40. data/lib/unitsdb/commands/release.rb +12 -9
  41. data/lib/unitsdb/commands/search.rb +12 -11
  42. data/lib/unitsdb/commands/ucum/check.rb +42 -29
  43. data/lib/unitsdb/commands/ucum/formatter.rb +2 -1
  44. data/lib/unitsdb/commands/ucum/matcher.rb +23 -9
  45. data/lib/unitsdb/commands/ucum/update.rb +14 -13
  46. data/lib/unitsdb/commands/ucum/updater.rb +40 -6
  47. data/lib/unitsdb/commands/ucum/xml_parser.rb +0 -2
  48. data/lib/unitsdb/commands/ucum.rb +44 -4
  49. data/lib/unitsdb/commands/validate/identifiers.rb +2 -4
  50. data/lib/unitsdb/commands/validate/qudt_references.rb +111 -0
  51. data/lib/unitsdb/commands/validate/references.rb +36 -19
  52. data/lib/unitsdb/commands/validate/si_references.rb +3 -5
  53. data/lib/unitsdb/commands/validate/ucum_references.rb +105 -0
  54. data/lib/unitsdb/commands/validate.rb +67 -11
  55. data/lib/unitsdb/commands.rb +20 -0
  56. data/lib/unitsdb/database.rb +90 -52
  57. data/lib/unitsdb/dimension.rb +1 -4
  58. data/lib/unitsdb/dimension_details.rb +0 -1
  59. data/lib/unitsdb/dimensions.rb +0 -2
  60. data/lib/unitsdb/errors.rb +7 -0
  61. data/lib/unitsdb/prefix.rb +0 -4
  62. data/lib/unitsdb/prefix_reference.rb +0 -2
  63. data/lib/unitsdb/prefixes.rb +0 -1
  64. data/lib/unitsdb/quantities.rb +0 -2
  65. data/lib/unitsdb/quantity.rb +0 -6
  66. data/lib/unitsdb/qudt.rb +100 -0
  67. data/lib/unitsdb/root_unit_reference.rb +0 -3
  68. data/lib/unitsdb/scale.rb +0 -4
  69. data/lib/unitsdb/scale_reference.rb +0 -2
  70. data/lib/unitsdb/scales.rb +0 -2
  71. data/lib/unitsdb/si_derived_base.rb +0 -2
  72. data/lib/unitsdb/ucum.rb +14 -10
  73. data/lib/unitsdb/unit.rb +0 -10
  74. data/lib/unitsdb/unit_reference.rb +0 -2
  75. data/lib/unitsdb/unit_system.rb +1 -3
  76. data/lib/unitsdb/unit_system_reference.rb +0 -2
  77. data/lib/unitsdb/unit_systems.rb +0 -2
  78. data/lib/unitsdb/units.rb +0 -2
  79. data/lib/unitsdb/utils.rb +32 -21
  80. data/lib/unitsdb/version.rb +5 -1
  81. data/lib/unitsdb.rb +62 -14
  82. data/unitsdb.gemspec +6 -3
  83. metadata +52 -13
  84. data/lib/unitsdb/commands/si_formatter.rb +0 -485
  85. data/lib/unitsdb/commands/si_matcher.rb +0 -470
  86. data/lib/unitsdb/commands/si_ttl_parser.rb +0 -100
  87. data/lib/unitsdb/commands/si_updater.rb +0 -212
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsdb
4
+ module Commands
5
+ module Qudt
6
+ # Formats output for QUDT matching results
7
+ module Formatter
8
+ module_function
9
+
10
+ # Print a direction header (UnitsDB → QUDT or QUDT → UnitsDB)
11
+ def print_direction_header(direction)
12
+ puts "\n=== #{direction} ===\n"
13
+ end
14
+
15
+ # Display results for QUDT → UnitsDB matching
16
+ def display_qudt_results(entity_type, matches, missing_matches,
17
+ unmatched_qudt)
18
+ puts "\nResults for #{entity_type.capitalize} (QUDT → UnitsDB):"
19
+ puts " Matched: #{matches.size}"
20
+ puts " Missing matches (could be added): #{missing_matches.size}"
21
+ puts " Unmatched QUDT entities: #{unmatched_qudt.size}"
22
+
23
+ return if missing_matches.empty?
24
+
25
+ puts "\nPotential additions (QUDT #{entity_type} that could be added to UnitsDB):"
26
+ missing_matches.each do |match|
27
+ qudt_entity = match[:qudt_entity]
28
+ db_entity = match[:db_entity]
29
+
30
+ # Get entity IDs and names
31
+ db_id = get_db_entity_id(db_entity)
32
+ db_name = get_db_entity_name(db_entity)
33
+ qudt_name = get_qudt_entity_name(qudt_entity)
34
+ qudt_uri = qudt_entity.uri
35
+
36
+ case qudt_entity
37
+ when Unitsdb::QudtUnit
38
+ puts " - UnitsDB unit '#{db_name}' (#{db_id}) → QUDT unit '#{qudt_name}' (#{qudt_uri})"
39
+ when Unitsdb::QudtQuantityKind
40
+ puts " - UnitsDB quantity '#{db_name}' (#{db_id}) → QUDT quantity kind '#{qudt_name}' (#{qudt_uri})"
41
+ when Unitsdb::QudtDimensionVector
42
+ puts " - UnitsDB dimension '#{db_name}' (#{db_id}) → QUDT dimension vector '#{qudt_name}' (#{qudt_uri})"
43
+ when Unitsdb::QudtSystemOfUnits
44
+ puts " - UnitsDB unit system '#{db_name}' (#{db_id}) → QUDT system of units '#{qudt_name}' (#{qudt_uri})"
45
+ end
46
+ end
47
+ end
48
+
49
+ # Display missing QUDT entities analysis
50
+ def display_missing_qudt_entities(entity_type, unmatched_qudt)
51
+ return if unmatched_qudt.empty?
52
+
53
+ puts "\n#{'=' * 60}"
54
+ puts "MISSING QUDT ENTITIES ANALYSIS"
55
+ puts "=" * 60
56
+ puts "\nQUDT #{entity_type.capitalize} that don't exist in UnitsDB (#{unmatched_qudt.size} total):"
57
+ puts "\nThese are QUDT entities that have no corresponding entity in UnitsDB."
58
+ puts "Consider whether any of these should be added to UnitsDB.\n"
59
+
60
+ unmatched_qudt.each_with_index do |entity, index|
61
+ puts "\n#{index + 1}. #{format_qudt_entity_details(entity)}"
62
+ end
63
+
64
+ puts "\n#{'-' * 60}"
65
+ puts "RECOMMENDATION: Review these entities to determine if any should be added to UnitsDB."
66
+ puts "Focus on commonly used #{entity_type} that would benefit the UnitsDB community."
67
+ puts "-" * 60
68
+ end
69
+
70
+ # Format detailed information about a QUDT entity
71
+ def format_qudt_entity_details(entity)
72
+ case entity
73
+ when Unitsdb::QudtUnit
74
+ details = "UNIT: #{entity.label || 'No label'}"
75
+ details += "\n URI: #{entity.uri}"
76
+ details += "\n Symbol: #{entity.symbol}" if entity.symbol
77
+ details += "\n Description: #{entity.description}" if entity.description
78
+ details += "\n Quantity Kind: #{entity.has_quantity_kind}" if entity.has_quantity_kind
79
+ details += "\n Dimension Vector: #{entity.has_dimension_vector}" if entity.has_dimension_vector
80
+ details += "\n Conversion Multiplier: #{entity.conversion_multiplier}" if entity.conversion_multiplier
81
+ details
82
+ when Unitsdb::QudtQuantityKind
83
+ details = "QUANTITY KIND: #{entity.label || 'No label'}"
84
+ details += "\n URI: #{entity.uri}"
85
+ details += "\n Symbol: #{entity.symbol}" if entity.symbol
86
+ details += "\n Description: #{entity.description}" if entity.description
87
+ details += "\n Dimension Vector: #{entity.has_dimension_vector}" if entity.has_dimension_vector
88
+ details
89
+ when Unitsdb::QudtDimensionVector
90
+ details = "DIMENSION VECTOR: #{entity.label || 'No label'}"
91
+ details += "\n URI: #{entity.uri}"
92
+ details += "\n Description: #{entity.description}" if entity.description
93
+ if entity.respond_to?(:dimension_exponent_for_length)
94
+ exponents = []
95
+ exponents << "L:#{entity.dimension_exponent_for_length}" if entity.dimension_exponent_for_length != 0
96
+ exponents << "M:#{entity.dimension_exponent_for_mass}" if entity.dimension_exponent_for_mass != 0
97
+ exponents << "T:#{entity.dimension_exponent_for_time}" if entity.dimension_exponent_for_time != 0
98
+ exponents << "I:#{entity.dimension_exponent_for_electric_current}" if entity.dimension_exponent_for_electric_current != 0
99
+ exponents << "Θ:#{entity.dimension_exponent_for_thermodynamic_temperature}" if entity.dimension_exponent_for_thermodynamic_temperature != 0
100
+ exponents << "N:#{entity.dimension_exponent_for_amount_of_substance}" if entity.dimension_exponent_for_amount_of_substance != 0
101
+ exponents << "J:#{entity.dimension_exponent_for_luminous_intensity}" if entity.dimension_exponent_for_luminous_intensity != 0
102
+ details += "\n Exponents: #{exponents.join(', ')}" unless exponents.empty?
103
+ end
104
+ details
105
+ when Unitsdb::QudtSystemOfUnits
106
+ details = "SYSTEM OF UNITS: #{entity.label || 'No label'}"
107
+ details += "\n URI: #{entity.uri}"
108
+ details += "\n Abbreviation: #{entity.abbreviation}" if entity.abbreviation
109
+ details += "\n Description: #{entity.description}" if entity.description
110
+ details
111
+ else
112
+ "UNKNOWN ENTITY TYPE: #{entity.uri}"
113
+ end
114
+ end
115
+
116
+ # Display results for UnitsDB → QUDT matching
117
+ def display_db_results(entity_type, matches, missing_refs, unmatched_db)
118
+ puts "\nResults for #{entity_type.capitalize} (UnitsDB → QUDT):"
119
+ puts " Matched: #{matches.size}"
120
+ puts " Missing references (could be added): #{missing_refs.size}"
121
+ puts " Unmatched UnitsDB entities: #{unmatched_db.size}"
122
+
123
+ unless unmatched_db.empty?
124
+ puts "\nUnmatched UnitsDB #{entity_type}:"
125
+ unmatched_db.each do |entity|
126
+ id = get_db_entity_id(entity)
127
+ name = get_db_entity_name(entity)
128
+ puts " - #{name} (#{id})"
129
+ end
130
+ end
131
+
132
+ return if missing_refs.empty?
133
+
134
+ puts "\nPotential references (QUDT references that could be added to UnitsDB):"
135
+ missing_refs.each do |match|
136
+ qudt_entity = match[:qudt_entity]
137
+ db_entity = match[:db_entity]
138
+
139
+ # Get entity IDs and names
140
+ db_id = get_db_entity_id(db_entity)
141
+ db_name = get_db_entity_name(db_entity)
142
+ qudt_name = get_qudt_entity_name(qudt_entity)
143
+ qudt_uri = qudt_entity.uri
144
+
145
+ case qudt_entity
146
+ when Unitsdb::QudtUnit
147
+ puts " - UnitsDB unit '#{db_name}' (#{db_id}) → QUDT unit '#{qudt_name}' (#{qudt_uri})"
148
+ when Unitsdb::QudtQuantityKind
149
+ puts " - UnitsDB quantity '#{db_name}' (#{db_id}) → QUDT quantity kind '#{qudt_name}' (#{qudt_uri})"
150
+ when Unitsdb::QudtDimensionVector
151
+ puts " - UnitsDB dimension '#{db_name}' (#{db_id}) → QUDT dimension vector '#{qudt_name}' (#{qudt_uri})"
152
+ when Unitsdb::QudtSystemOfUnits
153
+ puts " - UnitsDB unit system '#{db_name}' (#{db_id}) → QUDT system of units '#{qudt_name}' (#{qudt_uri})"
154
+ end
155
+ end
156
+ end
157
+
158
+ # Helper to get db entity id
159
+ def get_db_entity_id(entity)
160
+ if entity.respond_to?(:identifiers) && entity.identifiers && !entity.identifiers.empty?
161
+ entity.identifiers.first.id
162
+ elsif entity.respond_to?(:id)
163
+ entity.id
164
+ else
165
+ "unknown-id"
166
+ end
167
+ end
168
+
169
+ # Helper to get db entity name
170
+ def get_db_entity_name(entity)
171
+ if entity.respond_to?(:names) && entity.names && !entity.names.empty?
172
+ entity.names.first.value
173
+ elsif entity.respond_to?(:short) && entity.short
174
+ entity.short
175
+ elsif entity.respond_to?(:name)
176
+ entity.name
177
+ else
178
+ "unknown-name"
179
+ end
180
+ end
181
+
182
+ # Helper to get qudt entity name
183
+ def get_qudt_entity_name(entity)
184
+ case entity
185
+ when Unitsdb::QudtUnit, Unitsdb::QudtQuantityKind, Unitsdb::QudtDimensionVector, Unitsdb::QudtSystemOfUnits
186
+ entity.label || "No label"
187
+ else
188
+ "unknown-name"
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end