latinum 1.3.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2015, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -21,46 +23,84 @@
21
23
  require 'bigdecimal'
22
24
  require 'bigdecimal/util'
23
25
 
26
+ require_relative 'error'
27
+
24
28
  module Latinum
25
- class DifferentResourceNameError < ArgumentError
26
- def initialize
27
- super "Cannot operate on different currencies!"
28
- end
29
- end
30
-
31
- # A fixed unit in a given named resource
29
+ # A Resource represents a fixed amount of a named currency or material.
32
30
  class Resource
33
- include Comparable
31
+ # Parse a string representation of a resource.
32
+ # @parameter string [String] e.g "5 NZD".
33
+ # @returns [Resource] The Resource that represents the parsed string.
34
+ def self.parse(string, default_name: nil)
35
+ amount, name = string.split(/\s+/, 2)
36
+
37
+ self.new(amount, name || default_name)
38
+ end
34
39
 
35
- attr :amount
36
- attr :name
40
+ # Load a string representation of a resource.
41
+ # @parameter string [String | Nil] e.g. "5 NZD" or nil.
42
+ # @returns [Resource | Nil] The Resource that represents the parsed string.
43
+ def self.load(string)
44
+ if string
45
+ # Remove any whitespaces
46
+ string = string.strip
47
+
48
+ parse(string) unless string.empty?
49
+ end
50
+ end
51
+
52
+ # Dump a string representatino of a resource.
53
+ # @parameter resource [Resource] The resource to dump.
54
+ # @returns [String | Nil] A string that represents the {Resource}.
55
+ def self.dump(resource)
56
+ resource.to_s if resource
57
+ end
58
+
59
+ include Comparable
37
60
 
38
61
  def initialize(amount, name)
39
62
  @amount = amount.to_d
40
63
  @name = name
41
64
  end
42
65
 
43
- # By default, we can only add and subtract if the name is the same
66
+ # The amount of the resource.
67
+ # @attribute [BigDecimal]
68
+ attr :amount
69
+
70
+ # The name of the resource.
71
+ # @attribute [String]
72
+ attr :name
73
+
74
+ # Add two resources. Must have the same name.
75
+ # @returns [Resource] A resource with the added amount.
44
76
  def + other
45
77
  raise DifferentResourceNameError if @name != other.name
46
78
 
47
79
  self.class.new(@amount + other.amount, @name)
48
80
  end
49
81
 
82
+ # Subtract two resources. Must have the same name.
83
+ # @returns [Resource] A resource with the subtracted amount.
50
84
  def - other
51
85
  raise DifferentResourceNameError if @name != other.name
52
86
 
53
87
  self.class.new(@amount - other.amount, @name)
54
88
  end
55
89
 
90
+ # Invert the amount of the resource.
91
+ # @returns [Resource] A resource with the negated amount.
56
92
  def -@
57
93
  self.class.new(-@amount, @name)
58
94
  end
59
95
 
96
+ # Multiplies the resource by a given factor.
97
+ # @returns [Resource] A resource with the updated amount.
60
98
  def * factor
61
99
  self.class.new(@amount * factor, @name)
62
100
  end
63
101
 
102
+ # Divides the resource by a given factor.
103
+ # @returns [Resource] A resource with the updated amount.
64
104
  def / factor
65
105
  if factor.is_a? self.class
66
106
  raise DifferentResourceNameError if @name != factor.name
@@ -71,6 +111,10 @@ module Latinum
71
111
  end
72
112
  end
73
113
 
114
+ # Compute a new resource using the given exchange rate for the specified name.
115
+ # @parameter rate [Numeric] The exchange rate to use.
116
+ # @parameter name [String] The name of the new resource.
117
+ # @parameter precision [Integer | Nil] The number of decimal places to round to.
74
118
  def exchange(rate, name, precision = nil)
75
119
  return self if @name == name
76
120
 
@@ -81,20 +125,28 @@ module Latinum
81
125
  self.class.new(exchanged_amount, name)
82
126
  end
83
127
 
128
+ # A human readable string representation of the resource amount and name.
129
+ # @returns [String] e.g. "5 NZD".
84
130
  def to_s
85
- @amount.to_s('F') + ' ' + @name.to_s
131
+ "#{@amount.to_s('F')} #{@name}"
132
+ end
133
+
134
+ # A human readable string representation of the resource amount.
135
+ # @returns [String] e.g. "5.00".
136
+ def to_digits
137
+ @amount.to_s('F')
86
138
  end
87
139
 
88
140
  def inspect
89
141
  "#<#{self.class.name} #{self.to_s.dump}>"
90
142
  end
91
143
 
92
- # Compare with another resource or a Numeric value.
144
+ # Compare with another {Resource} or a Numeric value.
93
145
  def <=> other
94
146
  if other.is_a? self.class
95
147
  result = @amount <=> other.amount
96
148
  return result unless result == 0
97
-
149
+
98
150
  result = @name <=> other.name
99
151
  return result
100
152
  elsif other.is_a? Numeric
@@ -107,30 +159,11 @@ module Latinum
107
159
  end
108
160
 
109
161
  def eql? other
110
- self.class.eql? other.class and @name.eql? other.name and @amount.eql? other.amount
111
- end
112
-
113
- class << self
114
- def parse(string, default_name: nil)
115
- amount, name = string.split(/\s+/, 2)
116
-
117
- self.new(amount, name || default_name)
118
- end
119
-
120
- def load(string)
121
- if string
122
- # Remove any whitespaces
123
- string = string.strip
124
-
125
- parse(string) unless string.empty?
126
- end
127
- end
128
-
129
- def dump(resource)
130
- resource.to_s if resource
131
- end
162
+ self.class.eql?(other.class) and @name.eql?(other.name) and @amount.eql?(other.amount)
132
163
  end
133
164
 
165
+ # Whether the amount of the resource is zero.
166
+ # @returns [Boolean]
134
167
  def zero?
135
168
  @amount.zero?
136
169
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2015, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -19,5 +21,5 @@
19
21
  # THE SOFTWARE.
20
22
 
21
23
  module Latinum
22
- VERSION = "1.3.1"
24
+ VERSION = "1.6.0"
23
25
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: latinum
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-11 00:00:00.000000000 Z
11
+ date: 2020-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.3'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.3'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec
28
+ name: covered
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 3.4.0
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 3.4.0
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,38 +52,40 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description:
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.4'
69
+ description:
56
70
  email:
57
- - samuel.williams@oriontransfer.co.nz
58
71
  executables: []
59
72
  extensions: []
60
73
  extra_rdoc_files: []
61
74
  files:
62
- - ".rspec"
63
- - ".simplecov"
64
- - ".travis.yml"
65
- - Gemfile
66
- - README.md
67
- - Rakefile
68
- - latinum.gemspec
69
75
  - lib/latinum.rb
70
76
  - lib/latinum/bank.rb
71
77
  - lib/latinum/collection.rb
72
78
  - lib/latinum/currencies/global.rb
79
+ - lib/latinum/error.rb
73
80
  - lib/latinum/formatters.rb
74
81
  - lib/latinum/resource.rb
75
82
  - lib/latinum/version.rb
76
- - spec/latinum/bank_spec.rb
77
- - spec/latinum/collection_spec.rb
78
- - spec/latinum/comparison_spec.rb
79
- - spec/latinum/formatters_spec.rb
80
- - spec/latinum/integrals_spec.rb
81
- - spec/latinum/resource_spec.rb
82
83
  homepage: https://github.com/ioquatix/latinum
83
84
  licenses:
84
85
  - MIT
85
- metadata: {}
86
- post_install_message:
86
+ metadata:
87
+ funding_uri: https://github.com/sponsors/ioquatix/
88
+ post_install_message:
87
89
  rdoc_options: []
88
90
  require_paths:
89
91
  - lib
@@ -91,23 +93,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
93
  requirements:
92
94
  - - ">="
93
95
  - !ruby/object:Gem::Version
94
- version: '0'
96
+ version: '2.5'
95
97
  required_rubygems_version: !ruby/object:Gem::Requirement
96
98
  requirements:
97
99
  - - ">="
98
100
  - !ruby/object:Gem::Version
99
101
  version: '0'
100
102
  requirements: []
101
- rubyforge_project:
102
- rubygems_version: 2.6.12
103
- signing_key:
103
+ rubygems_version: 3.1.2
104
+ signing_key:
104
105
  specification_version: 4
105
- summary: Latinum is a simple gem for managing resource computations, including money
106
- and minerals.
107
- test_files:
108
- - spec/latinum/bank_spec.rb
109
- - spec/latinum/collection_spec.rb
110
- - spec/latinum/comparison_spec.rb
111
- - spec/latinum/formatters_spec.rb
112
- - spec/latinum/integrals_spec.rb
113
- - spec/latinum/resource_spec.rb
106
+ summary: Provides immutable resource and money computations.
107
+ test_files: []
data/.rspec DELETED
@@ -1,4 +0,0 @@
1
- --color
2
- --format documentation
3
- --backtrace
4
- --warnings
data/.simplecov DELETED
@@ -1,9 +0,0 @@
1
-
2
- SimpleCov.start do
3
- add_filter "/spec/"
4
- end
5
-
6
- if ENV['TRAVIS']
7
- require 'coveralls'
8
- Coveralls.wear!
9
- end
@@ -1,12 +0,0 @@
1
- language: ruby
2
- sudo: false
3
- rvm:
4
- - 2.1.8
5
- - 2.2.4
6
- - 2.3.0
7
- - ruby-head
8
- - rbx-2
9
- env: COVERAGE=true
10
- matrix:
11
- allow_failures:
12
- - rvm: "rbx-2"
data/Gemfile DELETED
@@ -1,7 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
5
- group :test do
6
- gem 'coveralls', platforms: [:mri]
7
- end
data/README.md DELETED
@@ -1,276 +0,0 @@
1
- # Latinum
2
-
3
- Latinum is a library for resource and currency calculations. It provides immutable `Resource` objects for dealing with quantities of named resources with an arbitrary number of decimal places, and `Bank` objects for converting resources and formatting them for output. Latinum doesn't include any global state by default and thus is ideal for integration with other frameworks/libraries.
4
-
5
- [![Build Status](https://travis-ci.org/ioquatix/latinum.svg?branch=master)](https://travis-ci.org/ioquatix/latinum)
6
- [![Code Climate](https://codeclimate.com/github/ioquatix/latinum.svg)](https://codeclimate.com/github/ioquatix/latinum)
7
- [![Coverage Status](https://coveralls.io/repos/ioquatix/latinum/badge.svg)](https://coveralls.io/r/ioquatix/latinum)
8
-
9
- ## Motivation
10
-
11
- I was originally planning on using the [Money gem](https://github.com/RubyMoney/money), but it's [dependency on global state](https://github.com/RubyMoney/money/blob/39b617cca8f02c885cc8246e0aab3e9dc5f90e15/lib/money/currency.rb#L19-L21) makes it hard to use if you want to deal with money as an immutable value type.
12
-
13
- Additionally, I wanted to support BitCoin, Japanese Yen, etc. The money gem was heavily biased towards decimal currency. It had (~2012) [fields like `dollars` and `cents`](https://github.com/RubyMoney/money/issues/197) which don't really make sense and don't really align with the real world. These days they have fixed parts of the API, but it's a bit of a mess now, supporting both decimal and non-decimal values.
14
-
15
- Another problem I had at the time was the [concept of zero](https://github.com/RubyMoney/money/issues/195). It should be possible to have an additive (e.g. 0) and multiplicative identity (e.g. 1) do the right thing. In fact, in Latinum, you can multiply `Latinum::Resource` instances by a scalar and get a useful result (e.g. for computing discounts).
16
-
17
- Finally, because of the above problem, it was not obvious at the time how to sum up a collection of money instances correctly. In fact, this is still a problem and a separate gem, based on the `Latinum::Collection` concept, [was made](https://github.com/lulalala/money-collection). However, this all fits together in a rather haphazard way.
18
-
19
- Latinum addresses all these issues. It has an immutable value type `Latinum::Resource` which has a robust definition: A value (e.g. 5.0025) and a resource name (USD). The semantics of resources are well defined without the need for "Currency" state like the symbol, how many decimal places, etc. So, it suits well for serialization into a database, and for formatting to the user, there is `Latinum::Bank` which gives you the choice of how you decide to format things or exchange them, whether you want to round something off, etc.
20
-
21
- ## Installation
22
-
23
- Add this line to your application's Gemfile:
24
-
25
- gem 'latinum'
26
-
27
- And then execute:
28
-
29
- $ bundle
30
-
31
- Or install it yourself as:
32
-
33
- $ gem install latinum
34
-
35
- ## Usage
36
-
37
- Latinum has several core concepts:
38
-
39
- - A `Resource` represents an immutable value with a specific face name (e.g. `'USD'`).
40
- - A `Resource` can only be combined with resources with the same face name.
41
- - A `Bank` is responsible for managing currencies and formatting options.
42
- - A `Bank` can exchange currencies explicitly with a given set of exchange rates.
43
- - A `Collection` is responsible for adding currencies together and is completely deterministic.
44
-
45
- ### Resources and Collections
46
-
47
- To create a new resource, use a string for accuracy:
48
-
49
- > ten = Latinum::Resource.new("10.00", "NZD")
50
- => 10.0 NZD
51
- > ten.amount == "10.00".to_d
52
- => true
53
-
54
- You can add resources of different values but with the same name:
55
-
56
- > ten + ten
57
- => 20.0 NZD
58
-
59
- But, you can't add resources of different names together:
60
-
61
- > twenty = Latinum::Resource.new("20.00", "AUD")
62
- => 20.0 AUD
63
- > ten + twenty
64
- DifferentResourceNameError: Cannot operate on different currencies!
65
-
66
- To add multiple currencies together, use a collection:
67
-
68
- > collection = Latinum::Collection.new
69
- > collection << [ten, twenty]
70
- > collection.collect(&:to_s)
71
- => [10.0 NZD, 20.0 AUD]
72
-
73
- #### Calculating Totals
74
-
75
- The `Latinum::Collection` is the correct way to sum up a list of transactions or other items with an
76
- associated `Latinum::Resource`. Here is an example:
77
-
78
- <table class="listing transactions" data-model="Transaction">
79
- <thead>
80
- <tr>
81
- <th class="name">Name</th>
82
- <th class="date">Date</th>
83
- <th class="price">Price</th>
84
- <th class="quantity">Quantity</th>
85
- <th class="subtotal">Sub-total</th>
86
- <th class="tax_rate">Tax</th>
87
- <th class="total">Total</th>
88
- </tr>
89
- </thead>
90
- <tbody>
91
- <?r
92
- currencies = Set.new
93
-
94
- summary = {
95
- :subtotal => Latinum::Collection.new(currencies),
96
- :tax => Latinum::Collection.new(currencies),
97
- :total => Latinum::Collection.new(currencies)
98
- }
99
-
100
- invoice.transactions.each do |transaction|
101
- subtotal = transaction.subtotal
102
- summary[:subtotal] << subtotal
103
- summary[:tax] << subtotal * transaction.tax_rate.to_d
104
- summary[:total] << transaction.total
105
-
106
- ?>
107
- <tr data-id="#{transaction.id}" data-rev="#{transaction.rev}">
108
- <th class="name">#{f.text transaction.name}</th>
109
- <td class="date">#{f.text transaction.date}</td>
110
- <td class="price">#{f.text transaction.price}</td>
111
- <td class="quantity">#{f.quantity transaction}</td>
112
- <td class="subtotal">#{f.text subtotal}</td>
113
- <td class="tax_rate">#{f.tax transaction}</td>
114
- <td class="total">#{f.text transaction.total}</td>
115
- </tr>
116
- <?r end ?>
117
- </tbody>
118
- <tfoot>
119
- <?r currencies.each do |currency| ?>
120
- <tr>
121
- <td colspan="5">#{currency} Summary:</td>
122
- <td class="subtotal">#{f.text summary[:subtotal][currency]}</td>
123
- <td class="tax_rate">#{f.text summary[:tax][currency]}</td>
124
- <td class="total">#{f.text summary[:total][currency]}</td>
125
- <td></td>
126
- </tr>
127
- <?r end ?>
128
- </tfoot>
129
- </table>
130
-
131
- ### Banks and Exchange Rates
132
-
133
- The bank is responsible for formatting and exchange rates:
134
-
135
- require 'latinum/bank'
136
- require 'latinum/currencies/global'
137
-
138
- > bank = Latinum::Bank.new(Latinum::Currencies::Global)
139
- > bank << Latinum::ExchangeRate.new("NZD", "AUD", "0.5")
140
-
141
- > nzd = Latinum::Resource.new("10", "NZD")
142
- => 10.0 NZD
143
- > aud = bank.exchange nzd, "AUD"
144
- => 5.0 AUD
145
-
146
- Formatting an amount is typically required for presentation to the end user:
147
-
148
- > bank.format(nzd)
149
- => "$10.00 NZD"
150
-
151
- > bank.format(aud, :format => :compact)
152
- => "$5.00"
153
-
154
- The bank can also be used to parse currency, which will depend on the priority of currencies if a symbol that matches multiple currencies is supplied:
155
-
156
- > bank.parse("$5")
157
- => 5.0 USD
158
-
159
- > bank.parse("€5")
160
- => 5.0 EUR
161
-
162
- Currency codes take priority over symbols if specified:
163
-
164
- > bank.parse("€5 NZD")
165
- => 5.0 NZD
166
-
167
- ### Conversion To and From Integers
168
-
169
- For storage in traditional databases, you may prefer to use integers. Based on the precision of the currency, you can store integer representations:
170
-
171
- > resource = Latinum::Resource.new("1.12345678", "BTC")
172
-
173
- > 112345678 == bank.to_integral(resource)
174
- true
175
-
176
- > resource == bank.from_integral(112345678, "BTC")
177
- true
178
-
179
- As BitCoin has 8 decimal places, it requires an integer representation with at least 10^8.
180
-
181
- ### ActiveRecord Serialization
182
-
183
- Latinum can be easily used in a [ActiveRecord](https://github.com/rails/rails/tree/master/activerecord) model simply by declaring a serialized data-type for a string or text column, e.g.
184
-
185
- class Transaction < ActiveRecord::Base
186
- serialize :total, Latinum::Resource
187
- end
188
-
189
- It can be used like so:
190
-
191
- > transaction = Transaction.new(:total => "10 NZD")
192
- > transaction.total * 2
193
- => "20.0 NZD"
194
-
195
- To format the output, use a `Latinum::Bank`, e.g. assuming the bank is set up correctly:
196
-
197
- > bank.format(transaction.total)
198
- => "$20.00 NZD"
199
-
200
- > bank.format(transaction.total, name: nil)
201
- => "$20.00"
202
-
203
- > bank.format(transaction.total, symbol: nil)
204
- => "20.00 NZD"
205
-
206
- ### Relaxo Serialization
207
-
208
- Latinum is natively supported by [Relaxo](https://github.com/ioquatix/relaxo) (CouchDB) and as such can be used in [Relaxo models](https://github.com/ioquatix/relaxo-model) easily.
209
-
210
- require 'latinum'
211
- require 'relaxo/model'
212
- require 'relaxo/model/properties/latinum'
213
-
214
- class Transaction
215
- include Relaxo::Model
216
-
217
- property :name
218
- property :price, Attribute[Latinum::Resource]
219
- end
220
-
221
- db = Relaxo.connect('test')
222
- db.create!
223
-
224
- t = Transaction.create(db, price: Latinum::Resource.load("50 NZD"))
225
-
226
- t.price
227
- # => <Latinum::Resource "50.0 NZD">
228
-
229
- # Save and reload from database server:
230
- t.save
231
- t = Transaction.fetch(db, t.id)
232
-
233
- t.price
234
- # => <Latinum::Resource "50.0 NZD">
235
-
236
- It gets stored in the database like so:
237
-
238
- {
239
- "_id": "740f4728fc9a571d826688db2f004771",
240
- "_rev": "1-45a29c63311cfa0d5a765707184b2b3b",
241
- "type": "transaction",
242
- "price": [
243
- "50.0",
244
- "NZD"
245
- ]
246
- }
247
-
248
- ## Contributing
249
-
250
- 1. Fork it
251
- 2. Create your feature branch (`git checkout -b my-new-feature`)
252
- 3. Commit your changes (`git commit -am 'Add some feature'`)
253
- 4. Push to the branch (`git push origin my-new-feature`)
254
- 5. Create new Pull Request
255
-
256
- ## License
257
-
258
- Copyright, 2015, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
259
-
260
- Permission is hereby granted, free of charge, to any person obtaining a copy
261
- of this software and associated documentation files (the "Software"), to deal
262
- in the Software without restriction, including without limitation the rights
263
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
264
- copies of the Software, and to permit persons to whom the Software is
265
- furnished to do so, subject to the following conditions:
266
-
267
- The above copyright notice and this permission notice shall be included in
268
- all copies or substantial portions of the Software.
269
-
270
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
271
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
272
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
273
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
274
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
275
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
276
- THE SOFTWARE.