pivot_table 0.1.4 → 0.2.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +26 -8
- data/lib/pivot_table.rb +6 -5
- data/lib/pivot_table/configuration.rb +13 -0
- data/lib/pivot_table/grid.rb +9 -3
- data/pivot_table.gemspec +1 -1
- data/spec/pivot_table/configuration_spec.rb +18 -0
- data/spec/pivot_table/grid_spec.rb +69 -104
- data/spec/spec_helper.rb +2 -0
- data/spec/support/helpers.rb +7 -0
- data/spec/support/{shared_examples.rb → shared_examples_for_a_cell_collection_.rb} +0 -2
- data/spec/support/shared_examples_for_a_collection_of_columns.rb +30 -0
- data/spec/support/shared_examples_for_a_collection_of_rows.rb +23 -0
- data/spec/support/shared_examples_for_a_data_grid.rb +20 -0
- metadata +19 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2684137254bb56ddbe7d1f32a2d505494170d38c
|
4
|
+
data.tar.gz: 1d3d224b88c1df7c8980196e463ff6788f42cddd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e57ccdddfff53cff46227a1cce75f9640376cd08feff730a773e44f1316937609a0c9e2a5a217d804a7ca18db291901e7c6a3c736c469e4ed6acb70a618118d1
|
7
|
+
data.tar.gz: 315f28559f9ccf3d9f1addfcb5fa5e4ba58125c950a42c5c0b9cdeca575d62cae7a6341fa56790c1151ba64ddaa6a34adcf67de077e743400a9663f018867df0
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
# Pivot Table [](http://travis-ci.org/edjames/pivot_table) [](https://codeclimate.com/github/edjames/pivot_table)
|
2
|
-
|
1
|
+
# Pivot Table [](http://travis-ci.org/edjames/pivot_table) [](https://codeclimate.com/github/edjames/pivot_table) [](https://gemnasium.com/edjames/pivot_table)
|
3
2
|
|
4
3
|
A handy tool for transforming a dataset into a spreadsheet-style pivot table.
|
5
4
|
|
@@ -103,15 +102,35 @@ If you want to get the totals for rows, columns, or the entire grid, you can pas
|
|
103
102
|
g.rows[1].total
|
104
103
|
g.grand_total
|
105
104
|
|
105
|
+
#### Configuration Options
|
106
|
+
|
107
|
+
You can also provide additional configuration options when instantiating your Grid. Options are provided as a hash e.g.
|
108
|
+
|
109
|
+
grid = PivotTable::Grid.new(:sort => true) do |g|
|
110
|
+
g.source_data = data
|
111
|
+
g.column_name = :quarter
|
112
|
+
g.row_name = :city
|
113
|
+
g.value_name = :sales
|
114
|
+
end
|
115
|
+
|
116
|
+
Here are the available configuration options:
|
117
|
+
|
118
|
+
###### 1. Sort
|
119
|
+
|
120
|
+
**Usage:** `:sort => false`
|
121
|
+
|
122
|
+
**Default:** `true`
|
123
|
+
|
124
|
+
This option will automatically sort your data alphabetically based on your column and row headers. If you disable sorting your original data ordering will be preserved.
|
125
|
+
|
106
126
|
|
107
127
|
### Ruby Support
|
108
|
-
----------------
|
109
128
|
|
110
129
|
* 1.9.3
|
111
130
|
* 2.0.0
|
131
|
+
* 2.1.0
|
112
132
|
|
113
|
-
Contributing to PivotTable
|
114
|
-
---------------------
|
133
|
+
### Contributing to PivotTable
|
115
134
|
|
116
135
|
If you want to contribute:
|
117
136
|
|
@@ -123,7 +142,6 @@ If you want to contribute:
|
|
123
142
|
* Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.
|
124
143
|
* Please try not to mess with the Rakefile, version, or history.
|
125
144
|
|
126
|
-
Copyright
|
127
|
-
---------
|
145
|
+
### Copyright
|
128
146
|
|
129
|
-
Copyright (c)
|
147
|
+
Copyright (c) 2014 Ed James. See LICENSE for details.
|
data/lib/pivot_table.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
$: << File.dirname(__FILE__)
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require 'pivot_table/configuration'
|
4
|
+
require 'pivot_table/grid'
|
5
|
+
require 'pivot_table/cell_collection'
|
6
|
+
require 'pivot_table/column'
|
7
|
+
require 'pivot_table/row'
|
7
8
|
|
8
9
|
module PivotTable
|
9
|
-
VERSION =
|
10
|
+
VERSION = '0.2.0'
|
10
11
|
end
|
data/lib/pivot_table/grid.rb
CHANGED
@@ -2,10 +2,15 @@ module PivotTable
|
|
2
2
|
class Grid
|
3
3
|
|
4
4
|
attr_accessor :source_data, :row_name, :column_name, :value_name
|
5
|
-
attr_reader :columns, :rows, :data_grid
|
5
|
+
attr_reader :columns, :rows, :data_grid, :configuration
|
6
6
|
|
7
|
-
|
7
|
+
DEFAULT_OPTIONS = {
|
8
|
+
:sort => true
|
9
|
+
}
|
10
|
+
|
11
|
+
def initialize(opts = {}, &block)
|
8
12
|
yield(self) if block_given?
|
13
|
+
@configuration = Configuration.new(DEFAULT_OPTIONS.merge(opts))
|
9
14
|
end
|
10
15
|
|
11
16
|
def build
|
@@ -80,7 +85,8 @@ module PivotTable
|
|
80
85
|
private
|
81
86
|
|
82
87
|
def headers(method)
|
83
|
-
@source_data.collect { |c| c.send method }.uniq
|
88
|
+
hdrs = @source_data.collect { |c| c.send method }.uniq
|
89
|
+
configuration.sort ? hdrs.sort : hdrs
|
84
90
|
end
|
85
91
|
|
86
92
|
end
|
data/pivot_table.gemspec
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PivotTable
|
4
|
+
describe Configuration do
|
5
|
+
|
6
|
+
subject { described_class.new opts }
|
7
|
+
|
8
|
+
let(:opts) { { :sort => true, :other_setting => 'on' } }
|
9
|
+
|
10
|
+
its(:sort) { should be_true }
|
11
|
+
its(:other_setting) { should == 'on' }
|
12
|
+
|
13
|
+
context 'when setting does not exist' do
|
14
|
+
its(:i_do_not_exist) { should be_nil }
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -2,41 +2,8 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module PivotTable
|
4
4
|
describe Grid do
|
5
|
-
def build_object(id, row, column)
|
6
|
-
OpenStruct.new id: id, row_name: row, column_name: column
|
7
|
-
end
|
8
|
-
|
9
|
-
let(:d1) { build_object(1, 'r1', 'c1') }
|
10
|
-
let(:d2) { build_object(2, 'r1', 'c2') }
|
11
|
-
let(:d3) { build_object(3, 'r1', 'c3') }
|
12
|
-
let(:d4) { build_object(4, 'r2', 'c1') }
|
13
|
-
let(:d5) { build_object(5, 'r2', 'c2') }
|
14
|
-
let(:d6) { build_object(6, 'r2', 'c3') }
|
15
|
-
|
16
|
-
let(:data) { [d1, d2, d3, d4, d5, d6] }
|
17
|
-
|
18
|
-
let(:column_headers) { %w(c1 c2 c3) }
|
19
|
-
let(:row_headers) { %w(r1 r2) }
|
20
|
-
let(:row_0) { [d1, d2, d3] }
|
21
|
-
let(:row_1) { [d4, d5, d6] }
|
22
|
-
let(:column_0) { [d1, d4] }
|
23
|
-
let(:column_1) { [d2, d5] }
|
24
|
-
let(:column_2) { [d3, d6] }
|
25
|
-
let(:column_totals) { [d1.id + d4.id, d2.id + d5.id, d3.id + d6.id] }
|
26
|
-
let(:row_totals) { [d1.id + d2.id + d3.id, d4.id + d5.id + d6.id] }
|
27
|
-
let(:grand_total) { d1.id + d2.id + d3.id + d4.id + d5.id + d6.id }
|
28
|
-
|
29
|
-
let(:instance) do
|
30
|
-
Grid.new do |g|
|
31
|
-
g.source_data = data
|
32
|
-
g.row_name = :row_name
|
33
|
-
g.column_name = :column_name
|
34
|
-
g.value_name = :id
|
35
|
-
end
|
36
|
-
end
|
37
5
|
|
38
6
|
context 'accessors' do
|
39
|
-
subject { Grid.new }
|
40
7
|
it { should respond_to :source_data }
|
41
8
|
it { should respond_to :row_name }
|
42
9
|
it { should respond_to :column_name }
|
@@ -45,85 +12,83 @@ module PivotTable
|
|
45
12
|
it { should respond_to :grand_total }
|
46
13
|
end
|
47
14
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
let(:build_result) { instance.build }
|
55
|
-
specify { build_result.columns.length.should == 3 }
|
56
|
-
|
57
|
-
context 'column headers' do
|
58
|
-
subject { build_result.column_headers }
|
59
|
-
it { should == column_headers }
|
60
|
-
end
|
61
|
-
|
62
|
-
context '1st column' do
|
63
|
-
subject { build_result.columns[0] }
|
64
|
-
its(:header) { should == column_headers[0] }
|
65
|
-
its(:data) { should == column_0 }
|
66
|
-
its(:total) { should == column_totals[0] }
|
67
|
-
end
|
15
|
+
let(:d1) { build_data_object(1, 'r1', 'c1') }
|
16
|
+
let(:d2) { build_data_object(2, 'r1', 'c2') }
|
17
|
+
let(:d3) { build_data_object(3, 'r1', 'c3') }
|
18
|
+
let(:d4) { build_data_object(4, 'r2', 'c1') }
|
19
|
+
let(:d5) { build_data_object(5, 'r2', 'c2') }
|
20
|
+
let(:d6) { build_data_object(6, 'r2', 'c3') }
|
68
21
|
|
69
|
-
|
70
|
-
|
71
|
-
its(:header) { should == column_headers[1] }
|
72
|
-
its(:data) { should == column_1 }
|
73
|
-
its(:total) { should == column_totals[1] }
|
74
|
-
end
|
22
|
+
let(:sorted_data) { [d1, d2, d3, d4, d5, d6] }
|
23
|
+
let(:unsorted_data) { [d6, d4, d5, d3, d2, d1] }
|
75
24
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
25
|
+
let(:instance) do
|
26
|
+
described_class.new(config) do |g|
|
27
|
+
g.source_data = data
|
28
|
+
g.row_name = :row_name
|
29
|
+
g.column_name = :column_name
|
30
|
+
g.value_name = :id
|
81
31
|
end
|
82
32
|
end
|
83
33
|
|
84
|
-
|
85
|
-
let(:
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
its(:header) { should == row_headers[1] }
|
103
|
-
its(:data) { should == row_1 }
|
104
|
-
its(:total) { should == row_totals[1] }
|
105
|
-
end
|
34
|
+
context 'when data is already sorted' do
|
35
|
+
let(:config) { {} }
|
36
|
+
let(:data) { sorted_data }
|
37
|
+
|
38
|
+
let(:column_headers) { %w(c1 c2 c3) }
|
39
|
+
let(:row_headers) { %w(r1 r2) }
|
40
|
+
let(:row_0) { [d1, d2, d3] }
|
41
|
+
let(:row_1) { [d4, d5, d6] }
|
42
|
+
let(:column_0) { [d1, d4] }
|
43
|
+
let(:column_1) { [d2, d5] }
|
44
|
+
let(:column_2) { [d3, d6] }
|
45
|
+
let(:column_totals) { [d1.id + d4.id, d2.id + d5.id, d3.id + d6.id] }
|
46
|
+
let(:row_totals) { [d1.id + d2.id + d3.id, d4.id + d5.id + d6.id] }
|
47
|
+
let(:grand_total) { d1.id + d2.id + d3.id + d4.id + d5.id + d6.id }
|
48
|
+
|
49
|
+
it_behaves_like 'a collection of columns'
|
50
|
+
it_behaves_like 'a collection of rows'
|
51
|
+
it_behaves_like 'a data grid'
|
106
52
|
end
|
107
53
|
|
108
|
-
|
109
|
-
let(:
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
54
|
+
context 'sorting unordered data' do
|
55
|
+
let(:config) { { :sort => true } }
|
56
|
+
let(:data) { unsorted_data }
|
57
|
+
|
58
|
+
let(:column_headers) { %w(c1 c2 c3) }
|
59
|
+
let(:row_headers) { %w(r1 r2) }
|
60
|
+
let(:row_0) { [d1, d2, d3] }
|
61
|
+
let(:row_1) { [d4, d5, d6] }
|
62
|
+
let(:column_0) { [d1, d4] }
|
63
|
+
let(:column_1) { [d2, d5] }
|
64
|
+
let(:column_2) { [d3, d6] }
|
65
|
+
let(:column_totals) { [d1.id + d4.id, d2.id + d5.id, d3.id + d6.id] }
|
66
|
+
let(:row_totals) { [d1.id + d2.id + d3.id, d4.id + d5.id + d6.id] }
|
67
|
+
let(:grand_total) { d1.id + d2.id + d3.id + d4.id + d5.id + d6.id }
|
68
|
+
|
69
|
+
it_behaves_like 'a collection of columns'
|
70
|
+
it_behaves_like 'a collection of rows'
|
71
|
+
it_behaves_like 'a data grid'
|
72
|
+
end
|
120
73
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
74
|
+
context 'keep original data ordering' do
|
75
|
+
let(:config) { { :sort => false } }
|
76
|
+
let(:data) { unsorted_data }
|
77
|
+
|
78
|
+
let(:column_headers) { %w(c3 c1 c2) }
|
79
|
+
let(:row_headers) { %w(r2 r1) }
|
80
|
+
let(:row_0) { [d6, d4, d5] }
|
81
|
+
let(:row_1) { [d3, d1, d2] }
|
82
|
+
let(:column_0) { [d6, d3] }
|
83
|
+
let(:column_1) { [d4, d1] }
|
84
|
+
let(:column_2) { [d5, d2] }
|
85
|
+
let(:column_totals) { [d6.id + d3.id, d4.id + d1.id, d5.id + d2.id] }
|
86
|
+
let(:row_totals) { [d6.id + d4.id + d5.id, d3.id + d2.id + d1.id] }
|
87
|
+
let(:grand_total) { d1.id + d2.id + d3.id + d4.id + d5.id + d6.id }
|
88
|
+
|
89
|
+
it_behaves_like 'a collection of columns'
|
90
|
+
it_behaves_like 'a collection of rows'
|
91
|
+
it_behaves_like 'a data grid'
|
127
92
|
end
|
128
93
|
end
|
129
94
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
shared_examples "a cell collection" do
|
2
|
-
|
3
2
|
it { should respond_to :header }
|
4
3
|
it { should respond_to :data }
|
5
4
|
it { should respond_to :value_name }
|
@@ -16,5 +15,4 @@ shared_examples "a cell collection" do
|
|
16
15
|
its(:data) { should == attrs[:data] }
|
17
16
|
its(:value_name) { should == attrs[:value_name] }
|
18
17
|
end
|
19
|
-
|
20
18
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
shared_examples 'a collection of columns' do
|
2
|
+
let(:build_result) { instance.build }
|
3
|
+
specify { build_result.columns.length.should == 3 }
|
4
|
+
|
5
|
+
context 'column headers' do
|
6
|
+
subject { build_result.column_headers }
|
7
|
+
it { should == column_headers }
|
8
|
+
end
|
9
|
+
|
10
|
+
context '1st column' do
|
11
|
+
subject { build_result.columns[0] }
|
12
|
+
its(:header) { should == column_headers[0] }
|
13
|
+
its(:data) { should == column_0 }
|
14
|
+
its(:total) { should == column_totals[0] }
|
15
|
+
end
|
16
|
+
|
17
|
+
context '2nd column' do
|
18
|
+
subject { build_result.columns[1] }
|
19
|
+
its(:header) { should == column_headers[1] }
|
20
|
+
its(:data) { should == column_1 }
|
21
|
+
its(:total) { should == column_totals[1] }
|
22
|
+
end
|
23
|
+
|
24
|
+
context '3rd column' do
|
25
|
+
subject { build_result.columns[2] }
|
26
|
+
its(:header) { should == column_headers[2] }
|
27
|
+
its(:data) { should == column_2 }
|
28
|
+
its(:total) { should == column_totals[2] }
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
shared_examples 'a collection of rows' do
|
2
|
+
let(:build_result) { instance.build }
|
3
|
+
specify { build_result.rows.length.should == 2 }
|
4
|
+
|
5
|
+
context 'row headers' do
|
6
|
+
subject { build_result.row_headers }
|
7
|
+
it { should == row_headers }
|
8
|
+
end
|
9
|
+
|
10
|
+
context '1st row' do
|
11
|
+
subject { build_result.rows[0] }
|
12
|
+
its(:header) { should == row_headers[0] }
|
13
|
+
its(:data) { should == row_0 }
|
14
|
+
its(:total) { should == row_totals[0] }
|
15
|
+
end
|
16
|
+
|
17
|
+
context '2nd row' do
|
18
|
+
subject { build_result.rows[1] }
|
19
|
+
its(:header) { should == row_headers[1] }
|
20
|
+
its(:data) { should == row_1 }
|
21
|
+
its(:total) { should == row_totals[1] }
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
shared_examples 'a data grid' do
|
2
|
+
let(:build_result) { instance.build }
|
3
|
+
|
4
|
+
context 'preparing the grid' do
|
5
|
+
subject { build_result.prepare_grid }
|
6
|
+
it { should == [[nil, nil, nil], [nil, nil, nil]] }
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'populating the grid' do
|
10
|
+
subject { build_result.data_grid }
|
11
|
+
it { should == [row_0, row_1] }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'totals' do
|
15
|
+
subject { build_result }
|
16
|
+
its(:column_totals) { should == column_totals }
|
17
|
+
its(:row_totals) { should == row_totals }
|
18
|
+
its(:grand_total) { should == grand_total }
|
19
|
+
end
|
20
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pivot_table
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ed James
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '4.
|
47
|
+
version: '4.2'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '4.
|
54
|
+
version: '4.2'
|
55
55
|
description: Transform an ActiveRecord-ish data set into a pivot table of objects
|
56
56
|
email: ed.james.email@gmail.com
|
57
57
|
executables: []
|
@@ -70,14 +70,20 @@ files:
|
|
70
70
|
- lib/pivot_table.rb
|
71
71
|
- lib/pivot_table/cell_collection.rb
|
72
72
|
- lib/pivot_table/column.rb
|
73
|
+
- lib/pivot_table/configuration.rb
|
73
74
|
- lib/pivot_table/grid.rb
|
74
75
|
- lib/pivot_table/row.rb
|
75
76
|
- pivot_table.gemspec
|
76
77
|
- spec/pivot_table/column_spec.rb
|
78
|
+
- spec/pivot_table/configuration_spec.rb
|
77
79
|
- spec/pivot_table/grid_spec.rb
|
78
80
|
- spec/pivot_table/row_spec.rb
|
79
81
|
- spec/spec_helper.rb
|
80
|
-
- spec/support/
|
82
|
+
- spec/support/helpers.rb
|
83
|
+
- spec/support/shared_examples_for_a_cell_collection_.rb
|
84
|
+
- spec/support/shared_examples_for_a_collection_of_columns.rb
|
85
|
+
- spec/support/shared_examples_for_a_collection_of_rows.rb
|
86
|
+
- spec/support/shared_examples_for_a_data_grid.rb
|
81
87
|
homepage: https://github.com/edjames/pivot_table
|
82
88
|
licenses: []
|
83
89
|
metadata: {}
|
@@ -97,13 +103,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
103
|
version: '0'
|
98
104
|
requirements: []
|
99
105
|
rubyforge_project: pivot_table
|
100
|
-
rubygems_version: 2.
|
106
|
+
rubygems_version: 2.1.11
|
101
107
|
signing_key:
|
102
108
|
specification_version: 4
|
103
|
-
summary: pivot_table-0.
|
109
|
+
summary: pivot_table-0.2.0
|
104
110
|
test_files:
|
105
111
|
- spec/pivot_table/column_spec.rb
|
112
|
+
- spec/pivot_table/configuration_spec.rb
|
106
113
|
- spec/pivot_table/grid_spec.rb
|
107
114
|
- spec/pivot_table/row_spec.rb
|
108
115
|
- spec/spec_helper.rb
|
109
|
-
- spec/support/
|
116
|
+
- spec/support/helpers.rb
|
117
|
+
- spec/support/shared_examples_for_a_cell_collection_.rb
|
118
|
+
- spec/support/shared_examples_for_a_collection_of_columns.rb
|
119
|
+
- spec/support/shared_examples_for_a_collection_of_rows.rb
|
120
|
+
- spec/support/shared_examples_for_a_data_grid.rb
|