box_packer 1.2.0 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cb419643a33b63ce8d279f9baafa0c2e4c010300
4
- data.tar.gz: a5174fcc00bc4ccb58542182ac40a7aceef95f14
3
+ metadata.gz: 4659a59306f377ffb56826c4066f6a8cd59a3ed6
4
+ data.tar.gz: 1f789104af76b44e14a8aedada8cc4e1a8a7a9ff
5
5
  SHA512:
6
- metadata.gz: fa82429a9a668dafdc268f9bc85d46261b9b9742a31099c87cb37870ce8cc6af3b8c358cc5babd5ebfd8e39549caa16344aef181737fdb33a1616b1696423cf4
7
- data.tar.gz: 82af4730e2b2b13dc9868398a65b76f46561663ba0e158b606e8502aa3a4c569b9b42b7e22f83399420cbae3ad19368908c8fd0d01c4e3c036db594ed20e64f4
6
+ metadata.gz: 3d245edfff6dc2ba6af12e65dcab58215eb2b9ae21bb71b953d8f98c6421f237f699487f46ae946a3ea89a631cdb92c43f1c4fef5e7556748c45dedaba3e18e0
7
+ data.tar.gz: 9751c392ce1c08783d1c265b28677e6e53dca4bf0a1f5475c38d80af3b5610b65bf6d18ed5c68be52613b3195bd69085c36e77ed0615af68cd677497854c9b13
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  BoxPacker
2
2
  =========
3
3
 
4
+ [![Gem Version](https://badge.fury.io/rb/box_packer.svg)](http://badge.fury.io/rb/box_packer)
5
+
4
6
  A heuristic first-fit 3D bin packing algorithm with optional weight and bin limits.
5
7
 
6
8
  Installation
@@ -10,4 +10,3 @@ require 'box_packer/packing'
10
10
  require 'box_packer/svg_exporter'
11
11
  require 'box_packer/container'
12
12
  require 'box_packer/builder'
13
- require 'box_packer/version'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: box_packer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max White
@@ -11,63 +11,67 @@ cert_chain: []
11
11
  date: 2015-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rspec
14
+ name: attire
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.1'
20
- type: :development
19
+ version: '0.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.3
23
+ type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '3.1'
29
+ version: '0.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.3
27
33
  - !ruby/object:Gem::Dependency
28
- name: attire
34
+ name: rasem
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '0'
39
+ version: '0.6'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '0'
46
+ version: '0.6'
41
47
  - !ruby/object:Gem::Dependency
42
- name: rasem
48
+ name: rspec
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: '0.6'
48
- type: :runtime
53
+ version: '3.1'
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 3.1.0
57
+ type: :development
49
58
  prerelease: false
50
59
  version_requirements: !ruby/object:Gem::Requirement
51
60
  requirements:
52
61
  - - "~>"
53
62
  - !ruby/object:Gem::Version
54
- version: '0.6'
63
+ version: '3.1'
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 3.1.0
55
67
  description:
56
- email:
57
- - mushishi78@gmail.com
68
+ email: mushishi78@gmail.com
58
69
  executables: []
59
70
  extensions: []
60
71
  extra_rdoc_files: []
61
72
  files:
62
- - ".gitignore"
63
- - ".rspec"
64
- - ".rubocop.yml"
65
- - Gemfile
66
73
  - LICENSE.txt
67
74
  - README.md
68
- - Rakefile
69
- - box_packer.gemspec
70
- - examples/example1.svg
71
75
  - lib/box_packer.rb
72
76
  - lib/box_packer/box.rb
73
77
  - lib/box_packer/builder.rb
@@ -78,16 +82,7 @@ files:
78
82
  - lib/box_packer/packing.rb
79
83
  - lib/box_packer/position.rb
80
84
  - lib/box_packer/svg_exporter.rb
81
- - lib/box_packer/version.rb
82
- - spec/lib/box_spec.rb
83
- - spec/lib/container_spec.rb
84
- - spec/lib/dimensions_spec.rb
85
- - spec/lib/item_spec.rb
86
- - spec/lib/packer_spec.rb
87
- - spec/lib/packing_spec.rb
88
- - spec/spec_helper.rb
89
- - spec/support/matchers/yield_each_once.rb
90
- homepage: https://github.com/mushishi78/box_packer
85
+ homepage:
91
86
  licenses:
92
87
  - MIT
93
88
  metadata: {}
@@ -110,14 +105,5 @@ rubyforge_project:
110
105
  rubygems_version: 2.2.2
111
106
  signing_key:
112
107
  specification_version: 4
113
- summary: Heuristic first-fit 3D bin-packing algorithmwith optional weight and bin
114
- limits.
115
- test_files:
116
- - spec/lib/box_spec.rb
117
- - spec/lib/container_spec.rb
118
- - spec/lib/dimensions_spec.rb
119
- - spec/lib/item_spec.rb
120
- - spec/lib/packer_spec.rb
121
- - spec/lib/packing_spec.rb
122
- - spec/spec_helper.rb
123
- - spec/support/matchers/yield_each_once.rb
108
+ summary: 3D bin-packing algorithm with optional weight and bin limits.
109
+ test_files: []
data/.gitignore DELETED
@@ -1,15 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- *.bundle
11
- *.so
12
- *.o
13
- *.a
14
- mkmf.log
15
- *.gem
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --require spec_helper
@@ -1,4 +0,0 @@
1
- Metrics/LineLength:
2
- Max: 100
3
- Documentation:
4
- Enabled: false
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in box_packer.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1 +0,0 @@
1
- require 'bundler/gem_tasks'
@@ -1,24 +0,0 @@
1
- lib = File.expand_path('../lib', __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'box_packer/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'box_packer'
7
- spec.version = BoxPacker::VERSION
8
- spec.authors = ['Max White']
9
- spec.email = ['mushishi78@gmail.com']
10
- spec.summary = 'Heuristic first-fit 3D bin-packing algorithm' \
11
- 'with optional weight and bin limits.'
12
- spec.homepage = 'https://github.com/mushishi78/box_packer'
13
- spec.license = 'MIT'
14
-
15
- spec.files = `git ls-files -z`.split("\x0")
16
- spec.executables = spec.files.grep(/^bin/) { |f| File.basename(f) }
17
- spec.test_files = spec.files.grep(/^(test|spec|features)/)
18
- spec.require_paths = ['lib']
19
-
20
- spec.add_development_dependency 'rspec', '~> 3.1'
21
-
22
- spec.add_dependency 'attire', '~> 0'
23
- spec.add_dependency 'rasem', '~> 0.6'
24
- end
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" standalone="no"?>
2
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
3
- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
- <svg width="1045.0" height="1185.0" version="1.1"
5
- xmlns="http://www.w3.org/2000/svg">
6
- <rect x="15" y="15" width="500.0" height="375.0" rx="0" ry="0" style="stroke:black;stroke-width:1;fill:white;"/><rect x="15.0" y="15.0" width="375.0" height="375.0" rx="0" ry="0" style="fill:blue;"/><text x="199.5" y="202.5" style="fill:black;"><tspan x="199.5" dy="0em">Hat</tspan></text><rect x="390.0" y="15.0" width="125.0" height="250.0" rx="0" ry="0" style="fill:green;"/><text x="447.5" y="140.0" style="fill:black;"><tspan x="447.5" dy="0em">Shoes</tspan></text><rect x="390.0" y="265.0" width="125.0" height="125.0" rx="0" ry="0" style="fill:orange;"/><text x="446.5" y="327.5" style="fill:black;"><tspan x="446.5" dy="0em">Dragon</tspan></text><rect x="15.0" y="15.0" width="375.0" height="250.0" rx="0" ry="0" style="fill:red;"/><text x="199.5" y="140.0" style="fill:black;"><tspan x="199.5" dy="0em">Bag</tspan></text><rect x="15.0" y="265.0" width="375.0" height="125.0" rx="0" ry="0" style="fill:purple;"/><text x="195.5" y="327.5" style="fill:black;"><tspan x="195.5" dy="0em">Slipper</tspan></text><rect x="530.0" y="15" width="500.0" height="375.0" rx="0" ry="0" style="stroke:black;stroke-width:1;fill:white;"/><rect x="530.0" y="265.0" width="375.0" height="125.0" rx="0" ry="0" style="fill:purple;"/><text x="710.5" y="327.5" style="fill:black;"><tspan x="710.5" dy="0em">Slipper</tspan></text><rect x="530.0" y="15.0" width="375.0" height="250.0" rx="0" ry="0" style="fill:red;"/><text x="714.5" y="140.0" style="fill:black;"><tspan x="714.5" dy="0em">Bag</tspan></text><rect x="905.0" y="265.0" width="125.0" height="125.0" rx="0" ry="0" style="fill:orange;"/><text x="961.5" y="327.5" style="fill:black;"><tspan x="961.5" dy="0em">Dragon</tspan></text><rect x="905.0" y="15.0" width="125.0" height="250.0" rx="0" ry="0" style="fill:green;"/><text x="962.5" y="140.0" style="fill:black;"><tspan x="962.5" dy="0em">Shoes</tspan></text><rect x="530.0" y="15.0" width="375.0" height="375.0" rx="0" ry="0" style="fill:blue;"/><text x="714.5" y="202.5" style="fill:black;"><tspan x="714.5" dy="0em">Hat</tspan></text><rect x="15" y="405.0" width="375.0" height="250.0" rx="0" ry="0" style="stroke:black;stroke-width:1;fill:white;"/><rect x="15.0" y="405.0" width="375.0" height="125.0" rx="0" ry="0" style="fill:blue;"/><text x="199.5" y="467.5" style="fill:black;"><tspan x="199.5" dy="0em">Hat</tspan></text><rect x="15.0" y="530.0" width="250.0" height="125.0" rx="0" ry="0" style="fill:red;"/><text x="137.0" y="592.5" style="fill:black;"><tspan x="137.0" dy="0em">Bag</tspan></text><rect x="265.0" y="530.0" width="125.0" height="125.0" rx="0" ry="0" style="fill:purple;"/><text x="320.5" y="592.5" style="fill:black;"><tspan x="320.5" dy="0em">Slipper</tspan></text><rect x="15.0" y="405.0" width="250.0" height="250.0" rx="0" ry="0" style="fill:green;"/><text x="135.0" y="530.0" style="fill:black;"><tspan x="135.0" dy="0em">Shoes</tspan></text><rect x="265.0" y="405.0" width="125.0" height="250.0" rx="0" ry="0" style="fill:orange;"/><text x="321.5" y="530.0" style="fill:black;"><tspan x="321.5" dy="0em">Dragon</tspan></text><rect x="405.0" y="405.0" width="375.0" height="250.0" rx="0" ry="0" style="stroke:black;stroke-width:1;fill:white;"/><rect x="655.0" y="405.0" width="125.0" height="250.0" rx="0" ry="0" style="fill:orange;"/><text x="711.5" y="530.0" style="fill:black;"><tspan x="711.5" dy="0em">Dragon</tspan></text><rect x="405.0" y="405.0" width="250.0" height="250.0" rx="0" ry="0" style="fill:green;"/><text x="525.0" y="530.0" style="fill:black;"><tspan x="525.0" dy="0em">Shoes</tspan></text><rect x="655.0" y="530.0" width="125.0" height="125.0" rx="0" ry="0" style="fill:purple;"/><text x="710.5" y="592.5" style="fill:black;"><tspan x="710.5" dy="0em">Slipper</tspan></text><rect x="405.0" y="530.0" width="250.0" height="125.0" rx="0" ry="0" style="fill:red;"/><text x="527.0" y="592.5" style="fill:black;"><tspan x="527.0" dy="0em">Bag</tspan></text><rect x="405.0" y="405.0" width="375.0" height="125.0" rx="0" ry="0" style="fill:blue;"/><text x="589.5" y="467.5" style="fill:black;"><tspan x="589.5" dy="0em">Hat</tspan></text><rect x="15" y="670.0" width="250.0" height="500.0" rx="0" ry="0" style="stroke:black;stroke-width:1;fill:white;"/><rect x="15.0" y="670.0" width="125.0" height="375.0" rx="0" ry="0" style="fill:blue;"/><text x="74.5" y="857.5" style="fill:black;"><tspan x="74.5" dy="0em">Hat</tspan></text><rect x="140.0" y="670.0" width="125.0" height="375.0" rx="0" ry="0" style="fill:red;"/><text x="199.5" y="857.5" style="fill:black;"><tspan x="199.5" dy="0em">Bag</tspan></text><rect x="15.0" y="1045.0" width="250.0" height="125.0" rx="0" ry="0" style="fill:green;"/><text x="135.0" y="1107.5" style="fill:black;"><tspan x="135.0" dy="0em">Shoes</tspan></text><rect x="140.0" y="670.0" width="125.0" height="375.0" rx="0" ry="0" style="fill:purple;"/><text x="195.5" y="857.5" style="fill:black;"><tspan x="195.5" dy="0em">Slipper</tspan></text><rect x="15.0" y="1045.0" width="250.0" height="125.0" rx="0" ry="0" style="fill:orange;"/><text x="134.0" y="1107.5" style="fill:black;"><tspan x="134.0" dy="0em">Dragon</tspan></text><rect x="280.0" y="670.0" width="250.0" height="500.0" rx="0" ry="0" style="stroke:black;stroke-width:1;fill:white;"/><rect x="280.0" y="1045.0" width="250.0" height="125.0" rx="0" ry="0" style="fill:orange;"/><text x="399.0" y="1107.5" style="fill:black;"><tspan x="399.0" dy="0em">Dragon</tspan></text><rect x="405.0" y="670.0" width="125.0" height="375.0" rx="0" ry="0" style="fill:purple;"/><text x="460.5" y="857.5" style="fill:black;"><tspan x="460.5" dy="0em">Slipper</tspan></text><rect x="280.0" y="1045.0" width="250.0" height="125.0" rx="0" ry="0" style="fill:green;"/><text x="400.0" y="1107.5" style="fill:black;"><tspan x="400.0" dy="0em">Shoes</tspan></text><rect x="405.0" y="670.0" width="125.0" height="375.0" rx="0" ry="0" style="fill:red;"/><text x="464.5" y="857.5" style="fill:black;"><tspan x="464.5" dy="0em">Bag</tspan></text><rect x="280.0" y="670.0" width="125.0" height="375.0" rx="0" ry="0" style="fill:blue;"/><text x="339.5" y="857.5" style="fill:black;"><tspan x="339.5" dy="0em">Hat</tspan></text></svg>
@@ -1,3 +0,0 @@
1
- module BoxPacker
2
- VERSION = '1.2.0'
3
- end
@@ -1,52 +0,0 @@
1
- module BoxPacker
2
- describe Box do
3
- subject(:box) { Box.new(dimensions, position: position) }
4
- let(:dimensions) { Dimensions[25, 30, 10] }
5
- let(:position) { Position[10, 25, 5] }
6
- let(:item) { Item.new(Dimensions[5, 2, 1]) }
7
-
8
- context 'if no position is given' do
9
- let(:position) { nil }
10
-
11
- it 'defaults to origin position' do
12
- expect(box.position).to eql(Position[0, 0, 0])
13
- end
14
- end
15
-
16
- describe '#orient!' do
17
- before { box.orient! }
18
- it { expect(box.dimensions).to eql(Dimensions[30, 25, 10]) }
19
- end
20
-
21
- describe '#sub_boxes_args' do
22
- let(:expected_args) do
23
- [
24
- [Dimensions[20, 30, 10], position: Position[15, 25, 5]],
25
- [Dimensions[5, 28, 10], position: Position[10, 27, 5]],
26
- [Dimensions[5, 2, 9], position: Position[10, 25, 6]]
27
- ]
28
- end
29
-
30
- it 'calculates the correct dimensions and positions' do
31
- expect(box.send(:sub_boxes_args, item)).to eql(expected_args)
32
- end
33
- end
34
-
35
- describe '#sub_boxes' do
36
- it 'orders sub-boxes by volumes' do
37
- sub_boxes = box.sub_boxes(item)
38
- expect(sub_boxes[0].volume).to be >= (sub_boxes[1].volume)
39
- expect(sub_boxes[1].volume).to be >= (sub_boxes[2].volume)
40
- end
41
-
42
- context 'with an item that reaches a side' do
43
- let(:item) { Box.new(Dimensions[15, 2, 10]) }
44
-
45
- it 'only returns 2 sub-boxes' do
46
- sub_boxes = box.sub_boxes(item)
47
- expect(sub_boxes.length).to eql(2)
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,89 +0,0 @@
1
- module BoxPacker
2
- describe Container do
3
- subject(:container) { Container.new([25, 30, 15]) }
4
-
5
- it { expect(container.packings).to eql(nil) }
6
-
7
- context 'with items' do
8
- let(:items) do
9
- [
10
- Item.new([15, 24, 8], weight: 25),
11
- Item.new([2, 1, 2], weight: 6),
12
- Item.new([9, 9, 10], weight: 30)
13
- ]
14
- end
15
- before { container.items = items }
16
-
17
- context 'with container prepared' do
18
- before do
19
- container.send(:prepare_to_pack!)
20
- end
21
-
22
- describe '#prepare_to_pack!' do
23
- let(:expected_dimensions)do
24
- [
25
- Dimensions[24, 15, 8],
26
- Dimensions[2, 2, 1],
27
- Dimensions[10, 9, 9]
28
- ]
29
- end
30
-
31
- it { expect(container.items.map(&:dimensions)).to eql(expected_dimensions) }
32
- it { expect(container.packings).to eql([]) }
33
- end
34
-
35
- context 'with some items packed' do
36
- before do
37
- container.new_packing!
38
- container.packing << items[1]
39
- container.packing << items[2]
40
- end
41
-
42
- it { expect(container.packings.length).to eql(1) }
43
- it { expect(container.packing).to match_array([items[1], items[2]]) }
44
-
45
- describe '#new_packing!!' do
46
- before { container.new_packing! }
47
- it { expect(container.packings.length).to eql(2) }
48
- it { expect(container.packing).to eql([]) }
49
- end
50
- end
51
- end
52
-
53
- describe '#packable?' do
54
- context 'with no items' do
55
- before { container.items = [] }
56
- it { expect(container.send(:packable?)).to be(false) }
57
- end
58
-
59
- context 'with items that fit' do
60
- it { expect(container.send(:packable?)).to be(true) }
61
- end
62
-
63
- context 'with an item to large' do
64
- before { container.items[0].dimensions = Dimensions[26, 34, 8] }
65
- it { expect(container.send(:packable?)).to be(false) }
66
- end
67
-
68
- context 'with a weight limit thats lighter than one of the items' do
69
- before { container.weight_limit = 24 }
70
- it { expect(container.send(:packable?)).to be(false) }
71
- end
72
-
73
- context 'with a packings limit of one packing' do
74
- before { container.packings_limit = 1 }
75
-
76
- context 'with a weight limit thats lighter than items' do
77
- before { container.weight_limit = 50 }
78
- it { expect(container.send(:packable?)).to be(false) }
79
- end
80
-
81
- context 'with a weight limit thats heavier than items' do
82
- before { container.weight_limit = 70 }
83
- it { expect(container.send(:packable?)).to be(true) }
84
- end
85
- end
86
- end
87
- end
88
- end
89
- end
@@ -1,54 +0,0 @@
1
- require_relative '../support/matchers/yield_each_once'
2
-
3
- module BoxPacker
4
- describe Dimensions do
5
- include BoxPacker::Matchers
6
- subject(:dimensions) { Dimensions[2, 10, 3] }
7
-
8
- describe '#volume' do
9
- it { expect(dimensions.volume).to eql(60) }
10
- end
11
-
12
- describe '#>=' do
13
- context 'when compared with Dimensions that are all bigger' do
14
- let(:other_dimensions) { Dimensions[1, 5, 2] }
15
- it { expect(dimensions >= other_dimensions).to be(true) }
16
- end
17
-
18
- context 'when compared with Dimensions where some are bigger and some are equal' do
19
- let(:other_dimensions) { Dimensions[2, 5, 3] }
20
- it { expect(dimensions >= other_dimensions).to be(true) }
21
- end
22
-
23
- context 'when compared with Dimensions that are all equal' do
24
- let(:other_dimensions) { Dimensions[2, 10, 3] }
25
- it { expect(dimensions >= other_dimensions).to be(true) }
26
- end
27
-
28
- context 'when compared with Dimensions where some are bigger and some are smaller' do
29
- let(:other_dimensions) { Dimensions[5, 5, 1] }
30
- it { expect(dimensions >= other_dimensions).to be(false) }
31
- end
32
-
33
- context 'when compared with Dimensions where none are bigger' do
34
- let(:other_dimensions) { Dimensions[5, 15, 11] }
35
- it { expect(dimensions >= other_dimensions).to be(false) }
36
- end
37
- end
38
-
39
- describe '#each_rotation' do
40
- let(:rotations)do
41
- [
42
- Dimensions[2, 10, 3],
43
- Dimensions[2, 3, 10],
44
- Dimensions[10, 2, 3],
45
- Dimensions[10, 3, 2],
46
- Dimensions[3, 10, 2],
47
- Dimensions[3, 2, 10]
48
- ]
49
- end
50
-
51
- it { expect { |b| dimensions.each_rotation(&b) }.to yield_each_once(rotations) }
52
- end
53
- end
54
- end
@@ -1,27 +0,0 @@
1
- module BoxPacker
2
- describe Item do
3
- subject(:item) { Item.new(dimensions) }
4
- let(:dimensions) { [12, 5, 7] }
5
-
6
- describe '#fit_into' do
7
- context 'when box is larger than box' do
8
- let(:box) { Box.new(Dimensions[6, 15, 9]) }
9
- let(:rotated_dimensions) { Dimensions[5, 12, 7] }
10
-
11
- it 'fits and orientation is rotated to fit' do
12
- expect(item.fit_into?(box)).to be(true)
13
- expect(item.dimensions).to eql(rotated_dimensions)
14
- end
15
- end
16
-
17
- context 'when other box has a smaller side than box' do
18
- let(:box) { Box.new(Dimensions[11, 6, 7]) }
19
-
20
- it 'does not fit and orientation is unchanged' do
21
- expect(item.fit_into?(box)).to be(false)
22
- expect(item.dimensions).to eql(Dimensions[*dimensions])
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,80 +0,0 @@
1
- module BoxPacker
2
- describe Packer do
3
- subject(:container) { Container.new(dimensions) }
4
- let(:dimensions) { [10, 15, 5] }
5
- let(:opts) { nil }
6
- let(:items)do
7
- [
8
- Item.new([1, 1, 1], weight: 1),
9
- Item.new([3, 1, 1], weight: 6),
10
- Item.new([5, 5, 1], weight: 15),
11
- Item.new([5, 5, 5], weight: 20)
12
- ]
13
- end
14
-
15
- describe '#pack' do
16
- context 'with items that fit exactly in one packing' do
17
- before do
18
- 20.times { container.items << items[0].dup }
19
- 10.times { container.items << items[1].dup }
20
- 8.times { container.items << items[2].dup }
21
- 4.times { container.items << items[3].dup }
22
- end
23
-
24
- it do
25
- expect(container.pack!).to eql(1)
26
- expect(container.packed_successfully).to be(true)
27
- end
28
- end
29
-
30
- context 'with items that fit exactly in three packings' do
31
- before do
32
- 35.times { container.items << items[0].dup }
33
- 30.times { container.items << items[1].dup }
34
- 10.times { container.items << items[2].dup }
35
- 15.times { container.items << items[3].dup }
36
- end
37
-
38
- it do
39
- expect(container.pack!).to eql(3)
40
- expect(container.packed_successfully).to be(true)
41
- end
42
- end
43
-
44
- context 'with a packing limit of one and too many items' do
45
- before do
46
- container.packings_limit = 1
47
- 35.times { container.items << items[0].dup }
48
- 30.times { container.items << items[1].dup }
49
- 10.times { container.items << items[2].dup }
50
- 15.times { container.items << items[3].dup }
51
- end
52
-
53
- it do
54
- expect(container.pack!).to be(false)
55
- expect(container.packed_successfully).to be(false)
56
- end
57
- end
58
-
59
- context 'with random container and random items' do
60
- let(:dimensions) { [x, y, z] }
61
- let(:x) { rand(1..75) }
62
- let(:y) { rand(1..75) }
63
- let(:z) { rand(1..75) }
64
-
65
- let(:items) do
66
- (1..rand(1..100)).map do
67
- Item.new([x / rand(1..5), y / rand(1..5), z / rand(1..5)])
68
- end
69
- end
70
-
71
- before do
72
- container.items = items
73
- container.pack!
74
- end
75
-
76
- it { expect(container.packed_successfully).to be(true) }
77
- end
78
- end
79
- end
80
- end
@@ -1,76 +0,0 @@
1
- module BoxPacker
2
- describe Packing do
3
- subject(:packing) { Packing.new(total_volume, total_weight) }
4
- let(:total_volume) { 200 }
5
- let(:total_weight) { 50 }
6
- let(:items) do
7
- [
8
- Item.new([2, 4, 1], weight: 5),
9
- Item.new([5, 2, 7], weight: 6),
10
- Item.new([8, 4, 2], weight: 3)
11
- ]
12
- end
13
-
14
- it 'defaults to empty' do
15
- expect(packing).to eql([])
16
- end
17
-
18
- describe '#<<' do
19
- before { items.each { |i| packing << i } }
20
-
21
- it { expect(packing.remaining_volume).to eql(58) }
22
- it { expect(packing.remaining_weight).to eql(36) }
23
-
24
- context 'with items that do not have weight' do
25
- let(:items) do
26
- [
27
- Item.new([2, 4, 1]),
28
- Item.new([5, 2, 7]),
29
- Item.new([8, 4, 2])
30
- ]
31
- end
32
-
33
- it { expect(packing.remaining_weight).to be(50) }
34
- end
35
-
36
- context 'with total_weight nil' do
37
- let(:total_weight) { nil }
38
- it { expect(packing.remaining_weight).to be(nil) }
39
- end
40
- end
41
-
42
- describe '#fit?' do
43
- before { items.each { |i| packing << i } }
44
-
45
- context 'with item that fits' do
46
- let(:item) { Item.new([1, 5, 5], weight: 5) }
47
- it { expect(packing.fit?(item)).to be(true) }
48
- end
49
-
50
- context 'with item thats already packed' do
51
- it { expect(packing.fit?(items[0])).to be(false) }
52
- end
53
-
54
- context 'with item thats too large' do
55
- let(:item) { Item.new([3, 5, 5], weight: 25) }
56
- it { expect(packing.fit?(item)).to be(false) }
57
- end
58
-
59
- context 'with item thats too heavy' do
60
- let(:item) { Item.new([1, 5, 5], weight: 45) }
61
- it { expect(packing.fit?(item)).to be(false) }
62
- end
63
-
64
- context 'with total_weight nil and item that fits' do
65
- let(:total_weight) { nil }
66
- let(:item) { Item.new([1, 5, 5], weight: 5) }
67
- it { expect(packing.fit?(item)).to be(true) }
68
- end
69
-
70
- context 'with item that has no weight but fits' do
71
- let(:item) { Item.new([1, 5, 5]) }
72
- it { expect(packing.fit?(item)).to be(true) }
73
- end
74
- end
75
- end
76
- end
@@ -1 +0,0 @@
1
- require 'box_packer'
@@ -1,38 +0,0 @@
1
- require 'rspec/matchers/built_in/yield'
2
-
3
- module BoxPacker
4
- module Matchers
5
- class YieldEachOnce
6
- attr_init :expected
7
-
8
- def matches?(block)
9
- @probe = RSpec::Matchers::BuiltIn::YieldProbe.probe(block)
10
- @actual = @probe.successive_yield_args
11
-
12
- @actual.each do |value|
13
- unless expected.delete(value)
14
- @failure_value = value
15
- return false
16
- end
17
- end
18
- true
19
- end
20
-
21
- def supports_block_expectations?
22
- true
23
- end
24
-
25
- def description
26
- 'be in expected array'
27
- end
28
-
29
- def failure_message
30
- "value #{@failure_value.to_a} was not in expected array"
31
- end
32
- end
33
-
34
- def yield_each_once(expected)
35
- YieldEachOnce.new(expected)
36
- end
37
- end
38
- end