squake 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7860b4b9cfbf3110355582ab95ce9faee0055fc6ea852b00093703fbcf8f7c8d
4
- data.tar.gz: 6f05154a58469f7f52f9730bf808a3005961b7ba29e7f6ce8fe47e47b27cc651
3
+ metadata.gz: b36b98d0bbe6be1cfa67c8b2ba81905f7bcdcc929308332b886548bbcd189b56
4
+ data.tar.gz: ee666e2bbd9f7535c824063dd20d5cb9ca90c72e384ff1ed8983bd7400f81d20
5
5
  SHA512:
6
- metadata.gz: d2065bbbe6bbbffa5067acf0810dbfe2c3ef32b50b5bce14b949f170a138f29ec16d2897093d9305af615e768ebcaa6da24873660572c24141e09f11b896cf08
7
- data.tar.gz: 53f6a57201c32df605f6d30932baa4408bc3eafd7c02fb6f2dff6f55d0313c1e0b0f501980aa93e17bcea5ecd3bc11491f81639d138aa4c60005e62237689e92
6
+ metadata.gz: d53fd77ab97f24cc6c3102500863865b7e0852d936b45862bfab7c946d301601b34fc0048135601518b645373ab8e67af1495e0acd039447c703c7284f239d84
7
+ data.tar.gz: 7869d17821522db8690f8c9a1fd0ad950cd8471e7176c3b20f9993b4ad4f01cfb9c6f3d8f1270fb30f77f5bc91f9c5bacb55873d857e60695575c82125100a6a
data/README.md CHANGED
@@ -34,7 +34,7 @@ You need a different API Key for production and sandbox.
34
34
 
35
35
  ## Usage
36
36
 
37
- Calculate emissions and include a price quote:
37
+ Initialize the client:
38
38
 
39
39
  ```ruby
40
40
  config = Squake::Config.new(
@@ -48,7 +48,36 @@ config = Squake::Config.new(
48
48
  # the SQUAKE client emits canonical log lines, e.g.
49
49
  # Request started http_method=get http_path=/api/v2/calculations
50
50
  client = Squake::Client.new(config: config)
51
+ ```
52
+
53
+ Calculate emissions
54
+
55
+ ```ruby
56
+ items = [
57
+ {
58
+ type: 'flight',
59
+ methodology: 'ICAO',
60
+ origin: 'BER',
61
+ destination: 'SIN',
62
+ booking_class: 'economy',
63
+ number_of_travellers: 2,
64
+ aircraft_type: '350',
65
+ external_reference: 'booking-id',
66
+ }
67
+ ]
51
68
 
69
+ # returns Squake::Model::Carbon
70
+ carbon = Squake::Calculation.create(
71
+ client: client, # required
72
+ items: items, # required
73
+ carbon_unit: 'gram', # optional, default: 'gram', other options: 'kilogram', 'tonne'
74
+ expand: [], # optional, default: [], allowed values: 'items' to enrich the response
75
+ )
76
+ ```
77
+
78
+ Calculate emissions and include a price quote:
79
+
80
+ ```ruby
52
81
  # Find all available item types and methodologies here:
53
82
  # https://docs-v2.squake.earth/group/endpoint-calculations
54
83
  items = [
@@ -71,6 +100,7 @@ pricing = Squake::CalculationWithPricing.quote(
71
100
  product: 'product-id', # required
72
101
  currency: 'EUR', # optional, default: 'EUR'
73
102
  carbon_unit: 'gram', # optional, default: 'gram', other options: 'kilogram', 'tonne'
103
+ expand: [], # optional, default: [], allowed values: 'items', 'product', 'price' to enrich the response
74
104
  )
75
105
  ```
76
106
 
@@ -98,3 +128,19 @@ Squake::Purchase.cancel(
98
128
  id: purchase.id, # required
99
129
  )
100
130
  ```
131
+
132
+ ## Publishing a new version
133
+
134
+ Have a Rubygems API key in your `~/.gem/credentials` file.
135
+
136
+ ```shell
137
+ ---
138
+ :rubygems_squake: rubygems_xxx
139
+ ```
140
+
141
+ Then run:
142
+
143
+ ```shell
144
+ gem build
145
+ gem push squake-0.1.0.gem --key=rubygems_squake
146
+ ```
@@ -0,0 +1,36 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # https://docs-v2.squake.earth/operation/operation-post-calculations
5
+ module Squake
6
+ class Calculation
7
+ extend T::Sig
8
+
9
+ ENDPOINT = T.let('/v2/calculations', String)
10
+
11
+ sig do
12
+ params(
13
+ client: Squake::Client,
14
+ items: T::Array[Squake::Model::Items::BaseType],
15
+ carbon_unit: String,
16
+ expand: T::Array[String],
17
+ ).returns(Squake::Model::Carbon)
18
+ end
19
+ def self.create(client:, items:, carbon_unit: 'gram', expand: [])
20
+ result = client.call(
21
+ path: ENDPOINT,
22
+ method: :post,
23
+ params: {
24
+ items: items.map(&:serialize),
25
+ carbon_unit: carbon_unit,
26
+ expand: expand,
27
+ },
28
+ )
29
+ raise Squake::APIError.new(response: result) unless result.success?
30
+
31
+ Squake::Model::Carbon.from_api_response(
32
+ T.cast(result.body, T::Hash[Symbol, T.untyped]),
33
+ )
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,53 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Squake
5
+ module Model
6
+ class Carbon < T::Struct
7
+ extend T::Sig
8
+
9
+ const :quantity, BigDecimal
10
+ const :unit, CarbonUnit, default: CarbonUnit::GRAM
11
+ const :items, T.nilable(T::Array[T::Hash[Symbol, T.untyped]]) # @TODO: resolve to typed items?
12
+
13
+ sig { params(response_body: T::Hash[Symbol, T.untyped]).returns(Squake::Model::Carbon) }
14
+ def self.from_api_response(response_body)
15
+ Squake::Model::Carbon.new(
16
+ quantity: BigDecimal(String(response_body.fetch(:quantity))),
17
+ unit: CarbonUnit.deserialize(response_body.fetch(:unit)),
18
+ items: response_body.fetch(:items, nil),
19
+ )
20
+ end
21
+
22
+ sig do
23
+ params(
24
+ unit: CarbonUnit,
25
+ ).returns(Carbon)
26
+ end
27
+ def in!(unit)
28
+ # this is a bit hacky, but it optimizes memory usages and we don't need `T.must`
29
+ # everywhere if we were to use a prop instead of a const.
30
+ @quantity = CarbonUnit.convert(quantity, self.unit, to: unit)
31
+ @unit = unit
32
+ self
33
+ end
34
+
35
+ sig do
36
+ params(
37
+ other: Carbon,
38
+ ).returns(Carbon)
39
+ end
40
+ def +(other)
41
+ other_qty = CarbonUnit.convert(other.quantity, other.unit, to: CarbonUnit::GRAM)
42
+ self_qty = CarbonUnit.convert(quantity, unit, to: CarbonUnit::GRAM)
43
+
44
+ Carbon.new(quantity: other_qty + self_qty)
45
+ end
46
+
47
+ sig { returns(Numeric) }
48
+ def fractional
49
+ quantity.to_f.round(unit.precision)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,105 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # as per International System of Units ("SI", or "metric system")
5
+ # see: https://www.nist.gov/pml/owm/si-units-mass
6
+ module Squake
7
+ module Model
8
+ class CarbonUnit < T::Enum
9
+ extend T::Sig
10
+
11
+ enums do
12
+ GRAM = new('gram')
13
+ KILOGRAM = new('kilogram')
14
+ TONNE = new('tonne')
15
+ end
16
+
17
+ sig { returns(String) }
18
+ def serialize_to_abbreviation
19
+ case self
20
+ when CarbonUnit::GRAM then 'g'
21
+ when CarbonUnit::KILOGRAM then 'kg'
22
+ when CarbonUnit::TONNE then 't'
23
+ else
24
+ T.absurd(self)
25
+ end
26
+ end
27
+
28
+ sig do
29
+ params(
30
+ carbon_quantity: T.any(Integer, Float, Rational, BigDecimal),
31
+ carbon_unit: CarbonUnit,
32
+ to: CarbonUnit,
33
+ ).returns(BigDecimal)
34
+ end
35
+ def self.convert(carbon_quantity, carbon_unit, to: CarbonUnit::GRAM)
36
+ case carbon_unit
37
+ when CarbonUnit::GRAM then gram_to_unit(carbon_quantity, to)
38
+ when CarbonUnit::KILOGRAM then kilogram_to_unit(carbon_quantity, to)
39
+ when CarbonUnit::TONNE then tonne_to_unit(carbon_quantity, to)
40
+ else
41
+ T.absurd(carbon_unit)
42
+ end
43
+ end
44
+
45
+ sig { returns(Integer) }
46
+ def precision
47
+ case self
48
+ when CarbonUnit::GRAM then 0
49
+ when CarbonUnit::KILOGRAM then 3
50
+ when CarbonUnit::TONNE then 6
51
+ else
52
+ T.absurd(self)
53
+ end
54
+ end
55
+
56
+ sig do
57
+ params(
58
+ carbon_quantity: T.any(Integer, Float, Rational, BigDecimal),
59
+ to: CarbonUnit,
60
+ ).returns(BigDecimal)
61
+ end
62
+ private_class_method def self.gram_to_unit(carbon_quantity, to)
63
+ case to
64
+ when CarbonUnit::GRAM then BigDecimal(carbon_quantity)
65
+ when CarbonUnit::KILOGRAM then BigDecimal(carbon_quantity) / 1_000
66
+ when CarbonUnit::TONNE then BigDecimal(carbon_quantity) / 1_000_000
67
+ else
68
+ T.absurd(to)
69
+ end
70
+ end
71
+
72
+ sig do
73
+ params(
74
+ carbon_quantity: T.any(Integer, Float, Rational, BigDecimal),
75
+ to: CarbonUnit,
76
+ ).returns(BigDecimal)
77
+ end
78
+ private_class_method def self.kilogram_to_unit(carbon_quantity, to)
79
+ case to
80
+ when CarbonUnit::GRAM then BigDecimal(carbon_quantity) * 1_000
81
+ when CarbonUnit::KILOGRAM then BigDecimal(carbon_quantity)
82
+ when CarbonUnit::TONNE then BigDecimal(carbon_quantity) / 1_000
83
+ else
84
+ T.absurd(to)
85
+ end
86
+ end
87
+
88
+ sig do
89
+ params(
90
+ carbon_quantity: T.any(Integer, Float, Rational, BigDecimal),
91
+ to: CarbonUnit,
92
+ ).returns(BigDecimal)
93
+ end
94
+ private_class_method def self.tonne_to_unit(carbon_quantity, to)
95
+ case to
96
+ when CarbonUnit::GRAM then BigDecimal(carbon_quantity) * 1_000_000
97
+ when CarbonUnit::KILOGRAM then BigDecimal(carbon_quantity) * 1_000
98
+ when CarbonUnit::TONNE then BigDecimal(carbon_quantity)
99
+ else
100
+ T.absurd(to)
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Squake
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - 'Team SQUAKE :rocket:'
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-14 00:00:00.000000000 Z
11
+ date: 2023-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -104,9 +104,12 @@ files:
104
104
  - README.md
105
105
  - lib/squake.rb
106
106
  - lib/squake/api_error.rb
107
+ - lib/squake/calculation.rb
107
108
  - lib/squake/calculation_with_pricing.rb
108
109
  - lib/squake/client.rb
109
110
  - lib/squake/config.rb
111
+ - lib/squake/model/carbon.rb
112
+ - lib/squake/model/carbon_unit.rb
110
113
  - lib/squake/model/items/base_type.rb
111
114
  - lib/squake/model/items/private_jet/squake.rb
112
115
  - lib/squake/model/price.rb