metro 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +19 -0
- data/changelog.md +8 -0
- data/lib/assets/missing_animation.png +0 -0
- data/lib/commands/generate_model.rb +2 -2
- data/lib/commands/generate_scene.rb +12 -2
- data/lib/commands/generate_view.rb +1 -1
- data/lib/gosu_ext/color.rb +1 -1
- data/lib/gosu_ext/image.rb +5 -0
- data/lib/metro.rb +18 -5
- data/lib/metro/animation/animation.rb +31 -0
- data/lib/metro/asset_path.rb +9 -0
- data/lib/metro/events/event_dictionary.rb +53 -0
- data/lib/metro/events/event_factory.rb +5 -3
- data/lib/metro/events/has_events.rb +5 -6
- data/lib/metro/game.rb +1 -1
- data/lib/metro/models/dimensions.rb +21 -0
- data/lib/metro/models/model.rb +149 -52
- data/lib/metro/models/model_factory.rb +4 -5
- data/lib/metro/models/{generic.rb → models/generic.rb} +0 -0
- data/lib/metro/models/{grid_drawer.rb → models/grid_drawer.rb} +4 -9
- data/lib/metro/models/{image.rb → models/image.rb} +11 -14
- data/lib/metro/models/models/label.rb +44 -0
- data/lib/metro/models/{menu.rb → models/menu.rb} +23 -18
- data/lib/metro/models/{rectangle.rb → models/rectangle.rb} +6 -5
- data/lib/metro/models/point.rb +23 -0
- data/lib/metro/models/properties/angle.rb +43 -0
- data/lib/metro/models/properties/animation.rb +143 -0
- data/lib/metro/models/properties/color.rb +113 -0
- data/lib/metro/models/properties/dimensions.rb +66 -0
- data/lib/metro/models/properties/font.rb +155 -0
- data/lib/metro/models/properties/image.rb +101 -0
- data/lib/metro/models/properties/numeric.rb +29 -0
- data/lib/metro/models/properties/position.rb +84 -0
- data/lib/metro/models/properties/property.rb +111 -0
- data/lib/metro/models/properties/scale.rb +89 -0
- data/lib/metro/models/properties/text.rb +66 -0
- data/lib/metro/models/properties/velocity.rb +80 -0
- data/lib/metro/models/scale.rb +21 -0
- data/lib/metro/scene.rb +19 -1
- data/lib/metro/scenes.rb +91 -31
- data/lib/metro/transitions/scene_transitions.rb +8 -0
- data/lib/metro/version.rb +1 -1
- data/lib/metro/views/view.rb +9 -1
- data/lib/templates/game/metro.tt +1 -1
- data/lib/templates/game/models/game_model.rb +3 -0
- data/lib/templates/game/scenes/brand_scene.rb +1 -1
- data/lib/templates/game/scenes/brand_to_title_scene.rb +1 -1
- data/lib/templates/game/scenes/game_scene.rb +19 -0
- data/lib/templates/game/scenes/title_scene.rb +1 -1
- data/lib/templates/game/views/brand_to_title.yaml +2 -2
- data/lib/templates/game/views/title.yaml +3 -3
- data/lib/templates/{model.rb.erb → model.rb.tt} +1 -1
- data/lib/templates/{scene.rb.erb → scene.rb.tt} +1 -1
- data/lib/templates/view.yaml.tt +6 -0
- data/spec/metro/models/models/label_spec.rb +110 -0
- data/spec/metro/models/properties/color_spec.rb +85 -0
- data/spec/metro/models/properties/font_spec.rb +129 -0
- data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
- data/spec/metro/models/properties/position_property_spec.rb +90 -0
- data/spec/metro/scenes_spec.rb +77 -0
- metadata +50 -16
- data/lib/metro/models/label.rb +0 -63
- data/lib/templates/view.yaml.erb +0 -32
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metro::Model::NumericProperty do
|
4
|
+
|
5
|
+
subject { described_class.new model }
|
6
|
+
let(:model) { "model" }
|
7
|
+
|
8
|
+
describe "#get" do
|
9
|
+
context "when the value is nil" do
|
10
|
+
context "when no default value has been specified" do
|
11
|
+
|
12
|
+
let(:expected_number) { 0.0 }
|
13
|
+
|
14
|
+
it "should return the default position" do
|
15
|
+
subject.get(nil).should eq expected_number
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when a default value has been specified" do
|
20
|
+
|
21
|
+
subject { described_class.new model, default: expected_number }
|
22
|
+
let(:expected_number) { 1.0 }
|
23
|
+
|
24
|
+
it "should return the specified default position" do
|
25
|
+
subject.get(nil).should eq expected_number
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when the value is a String" do
|
31
|
+
|
32
|
+
let(:number) { "4.3" }
|
33
|
+
let(:expected_number) { 4.3 }
|
34
|
+
|
35
|
+
it "should get the float value of the string" do
|
36
|
+
subject.get(number).should eq expected_number
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#set" do
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metro::Model::PositionProperty do
|
4
|
+
|
5
|
+
subject { described_class.new model }
|
6
|
+
let(:model) { "model" }
|
7
|
+
|
8
|
+
describe "#get" do
|
9
|
+
|
10
|
+
context "when the value is nil" do
|
11
|
+
context "when no default value has been specified" do
|
12
|
+
|
13
|
+
let(:expected_position) { Metro::Point.at 0.0, 0.0 }
|
14
|
+
|
15
|
+
it "should return the default position" do
|
16
|
+
subject.get(nil).should eq expected_position
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when a default value has been specified" do
|
21
|
+
|
22
|
+
subject { described_class.new model, default: expected_position }
|
23
|
+
let(:expected_position) { Metro::Point.at 4.0, 3.3 }
|
24
|
+
|
25
|
+
it "should return the specified default position" do
|
26
|
+
subject.get(nil).should eq expected_position
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when the value is a string" do
|
32
|
+
|
33
|
+
let(:point) { "22.0,33.0" }
|
34
|
+
let(:expected_position) { Metro::Point.at 22.0, 33.0 }
|
35
|
+
|
36
|
+
it "should return the position" do
|
37
|
+
subject.get(point).should eq expected_position
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
describe "#set" do
|
45
|
+
|
46
|
+
context "when the value is nil" do
|
47
|
+
context "when no default value has been specified" do
|
48
|
+
|
49
|
+
let(:expected_position) { "0.0,0.0,0.0" }
|
50
|
+
|
51
|
+
it "should return the default position" do
|
52
|
+
subject.set(nil).should eq expected_position
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when a default value has been specified" do
|
57
|
+
|
58
|
+
subject { described_class.new model, default: default_point }
|
59
|
+
let(:default_point) { Metro::Point.at 12, 24 }
|
60
|
+
let(:expected_position) { "12.0,24.0,0.0" }
|
61
|
+
|
62
|
+
it "should return the specified default position" do
|
63
|
+
subject.set(nil).should eq expected_position
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when the value is a point" do
|
69
|
+
|
70
|
+
let(:point) { Metro::Point.at 10.0, 20.0 }
|
71
|
+
let(:expected_position) { "10.0,20.0,0.0" }
|
72
|
+
|
73
|
+
it "should return the same position" do
|
74
|
+
subject.set(point).should eq expected_position
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "when the value is a string" do
|
79
|
+
|
80
|
+
let(:point) { "22.0,33.0" }
|
81
|
+
let(:expected_position) { "22.0,33.0,0.0" }
|
82
|
+
|
83
|
+
it "should return the position" do
|
84
|
+
subject.set(point).should eq expected_position
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metro::Scenes do
|
4
|
+
|
5
|
+
subject { described_class }
|
6
|
+
|
7
|
+
class SpecScene < Metro::Scene ; end
|
8
|
+
let(:existing_scene_name) { :spec }
|
9
|
+
|
10
|
+
describe ".find" do
|
11
|
+
context "when a scene does exist" do
|
12
|
+
|
13
|
+
let(:expected_value) { SpecScene }
|
14
|
+
|
15
|
+
it "should return the scene" do
|
16
|
+
subject.find(existing_scene_name).should eq expected_value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when a scene does not exist" do
|
21
|
+
let(:unknown_scene_name) { :unknown }
|
22
|
+
|
23
|
+
it "should return a missing scene" do
|
24
|
+
missing_scene = subject.find(unknown_scene_name)
|
25
|
+
missing_scene.missing_scene.should eq unknown_scene_name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".generate" do
|
31
|
+
let(:existing_scene_name) { :spec }
|
32
|
+
|
33
|
+
context "when the provided scene name does exist" do
|
34
|
+
|
35
|
+
let(:expected_scene_class) { SpecScene }
|
36
|
+
|
37
|
+
it "should return an instance of the scene" do
|
38
|
+
subject.generate(existing_scene_name).should be_kind_of expected_scene_class
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when the provided scene object does exist" do
|
43
|
+
|
44
|
+
let(:scene_instance) { SpecScene.new }
|
45
|
+
|
46
|
+
it "should return the same instance of scene" do
|
47
|
+
subject.generate(scene_instance).should eq scene_instance
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should process the scene through the post filters" do
|
52
|
+
subject.should_receive(:apply_post_filters)
|
53
|
+
subject.generate(existing_scene_name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe ".register_post_filter" do
|
58
|
+
|
59
|
+
class SpecScenesPostFilter
|
60
|
+
def self.filter(scene,options)
|
61
|
+
scene
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when a post filter is added" do
|
66
|
+
let(:post_filter) { SpecScenesPostFilter }
|
67
|
+
|
68
|
+
it "should be in the list of post filters" do
|
69
|
+
subject.register_post_filter SpecScenesPostFilter
|
70
|
+
subject.post_filters.should include(post_filter)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gosu
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- Rakefile
|
111
111
|
- bin/metro
|
112
112
|
- changelog.md
|
113
|
+
- lib/assets/missing_animation.png
|
113
114
|
- lib/commands/generate_game.rb
|
114
115
|
- lib/commands/generate_model.rb
|
115
116
|
- lib/commands/generate_scene.rb
|
@@ -118,10 +119,12 @@ files:
|
|
118
119
|
- lib/core_ext/numeric.rb
|
119
120
|
- lib/gosu_ext/color.rb
|
120
121
|
- lib/gosu_ext/gosu_constants.rb
|
122
|
+
- lib/gosu_ext/image.rb
|
121
123
|
- lib/locale/en.yml
|
122
124
|
- lib/locale/locale.rb
|
123
125
|
- lib/metro.rb
|
124
126
|
- lib/metro/animation/after_interval_factory.rb
|
127
|
+
- lib/metro/animation/animation.rb
|
125
128
|
- lib/metro/animation/animation_factory.rb
|
126
129
|
- lib/metro/animation/easing.rb
|
127
130
|
- lib/metro/animation/has_animations.rb
|
@@ -132,6 +135,7 @@ files:
|
|
132
135
|
- lib/metro/events/control_definition.rb
|
133
136
|
- lib/metro/events/controls.rb
|
134
137
|
- lib/metro/events/event_data.rb
|
138
|
+
- lib/metro/events/event_dictionary.rb
|
135
139
|
- lib/metro/events/event_factory.rb
|
136
140
|
- lib/metro/events/event_relay.rb
|
137
141
|
- lib/metro/events/has_events.rb
|
@@ -141,17 +145,32 @@ files:
|
|
141
145
|
- lib/metro/game/dsl.rb
|
142
146
|
- lib/metro/logging.rb
|
143
147
|
- lib/metro/missing_scene.rb
|
148
|
+
- lib/metro/models/dimensions.rb
|
144
149
|
- lib/metro/models/draws.rb
|
145
|
-
- lib/metro/models/generic.rb
|
146
|
-
- lib/metro/models/grid_drawer.rb
|
147
|
-
- lib/metro/models/image.rb
|
148
150
|
- lib/metro/models/key_value_coding.rb
|
149
|
-
- lib/metro/models/label.rb
|
150
|
-
- lib/metro/models/menu.rb
|
151
151
|
- lib/metro/models/model.rb
|
152
152
|
- lib/metro/models/model_factory.rb
|
153
|
-
- lib/metro/models/
|
153
|
+
- lib/metro/models/models/generic.rb
|
154
|
+
- lib/metro/models/models/grid_drawer.rb
|
155
|
+
- lib/metro/models/models/image.rb
|
156
|
+
- lib/metro/models/models/label.rb
|
157
|
+
- lib/metro/models/models/menu.rb
|
158
|
+
- lib/metro/models/models/rectangle.rb
|
159
|
+
- lib/metro/models/point.rb
|
160
|
+
- lib/metro/models/properties/angle.rb
|
161
|
+
- lib/metro/models/properties/animation.rb
|
162
|
+
- lib/metro/models/properties/color.rb
|
163
|
+
- lib/metro/models/properties/dimensions.rb
|
164
|
+
- lib/metro/models/properties/font.rb
|
165
|
+
- lib/metro/models/properties/image.rb
|
166
|
+
- lib/metro/models/properties/numeric.rb
|
167
|
+
- lib/metro/models/properties/position.rb
|
168
|
+
- lib/metro/models/properties/property.rb
|
169
|
+
- lib/metro/models/properties/scale.rb
|
170
|
+
- lib/metro/models/properties/text.rb
|
171
|
+
- lib/metro/models/properties/velocity.rb
|
154
172
|
- lib/metro/models/rectangle_bounds.rb
|
173
|
+
- lib/metro/models/scale.rb
|
155
174
|
- lib/metro/scene.rb
|
156
175
|
- lib/metro/scenes.rb
|
157
176
|
- lib/metro/template_message.rb
|
@@ -171,24 +190,32 @@ files:
|
|
171
190
|
- lib/templates/game/README.md.tt
|
172
191
|
- lib/templates/game/assets/brand.jpg
|
173
192
|
- lib/templates/game/metro.tt
|
193
|
+
- lib/templates/game/models/game_model.rb
|
174
194
|
- lib/templates/game/scenes/brand_scene.rb
|
175
195
|
- lib/templates/game/scenes/brand_to_title_scene.rb
|
196
|
+
- lib/templates/game/scenes/game_scene.rb
|
176
197
|
- lib/templates/game/scenes/title_scene.rb
|
177
198
|
- lib/templates/game/views/brand.yaml
|
178
199
|
- lib/templates/game/views/brand_to_title.yaml
|
179
200
|
- lib/templates/game/views/title.yaml
|
180
201
|
- lib/templates/message.erb
|
181
|
-
- lib/templates/model.rb.
|
182
|
-
- lib/templates/scene.rb.
|
183
|
-
- lib/templates/view.yaml.
|
202
|
+
- lib/templates/model.rb.tt
|
203
|
+
- lib/templates/scene.rb.tt
|
204
|
+
- lib/templates/view.yaml.tt
|
184
205
|
- metro.gemspec
|
185
206
|
- spec/core_ext/numeric_spec.rb
|
186
207
|
- spec/core_ext/string_spec.rb
|
187
208
|
- spec/gosu_ext/color_spec.rb
|
188
209
|
- spec/metro/models/key_value_coding_spec.rb
|
210
|
+
- spec/metro/models/models/label_spec.rb
|
211
|
+
- spec/metro/models/properties/color_spec.rb
|
212
|
+
- spec/metro/models/properties/font_spec.rb
|
213
|
+
- spec/metro/models/properties/numeric_property_spec.rb
|
214
|
+
- spec/metro/models/properties/position_property_spec.rb
|
189
215
|
- spec/metro/scene_spec.rb
|
190
216
|
- spec/metro/scene_views/json_view_spec.rb
|
191
217
|
- spec/metro/scene_views/yaml_view_spec.rb
|
218
|
+
- spec/metro/scenes_spec.rb
|
192
219
|
- spec/metro/views/view_spec.rb
|
193
220
|
- spec/spec_helper.rb
|
194
221
|
homepage: https://github.com/burtlo/metro
|
@@ -196,11 +223,12 @@ licenses: []
|
|
196
223
|
post_install_message: ! " ______ ___ _____\n ___ |/ /_____ __ /_______________\n
|
197
224
|
\ __ /|_/ / _ _ \\_ __/__ ___/_ __ \\\n _ / / / / __// /_ _ / /
|
198
225
|
/_/ /\n /_/ /_/ \\___/ \\__/ /_/ \\____/\n\n Thank you for installing
|
199
|
-
metro 0.1.
|
200
|
-
\ Changes:\n \n *
|
201
|
-
|
202
|
-
|
203
|
-
|
226
|
+
metro 0.1.6 / 2012-11-07.\n ---------------------------------------------------------------------\n
|
227
|
+
\ Changes:\n \n * Events are shared from superclasses to subclases.\n * Templates
|
228
|
+
updated to use GameScene and GameModel for each game.\n * Models are automatically
|
229
|
+
added to the update loop\n * Model properties now make it easier to store/retrieve
|
230
|
+
various\n common numeric, position font, image, and animation properties.\n \n\n
|
231
|
+
\ ---------------------------------------------------------------------\n"
|
204
232
|
rdoc_options: []
|
205
233
|
require_paths:
|
206
234
|
- lib
|
@@ -229,8 +257,14 @@ test_files:
|
|
229
257
|
- spec/core_ext/string_spec.rb
|
230
258
|
- spec/gosu_ext/color_spec.rb
|
231
259
|
- spec/metro/models/key_value_coding_spec.rb
|
260
|
+
- spec/metro/models/models/label_spec.rb
|
261
|
+
- spec/metro/models/properties/color_spec.rb
|
262
|
+
- spec/metro/models/properties/font_spec.rb
|
263
|
+
- spec/metro/models/properties/numeric_property_spec.rb
|
264
|
+
- spec/metro/models/properties/position_property_spec.rb
|
232
265
|
- spec/metro/scene_spec.rb
|
233
266
|
- spec/metro/scene_views/json_view_spec.rb
|
234
267
|
- spec/metro/scene_views/yaml_view_spec.rb
|
268
|
+
- spec/metro/scenes_spec.rb
|
235
269
|
- spec/metro/views/view_spec.rb
|
236
270
|
- spec/spec_helper.rb
|
data/lib/metro/models/label.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
module Metro
|
2
|
-
module Models
|
3
|
-
|
4
|
-
#
|
5
|
-
# Draws a string of text
|
6
|
-
#
|
7
|
-
# @example Using the Label in a view file
|
8
|
-
# model: "metro::models::label"
|
9
|
-
#
|
10
|
-
class Label < Model
|
11
|
-
|
12
|
-
attr_accessor :x, :y, :x_factor, :y_factor, :z_order
|
13
|
-
attr_accessor :size, :size, :font_family
|
14
|
-
|
15
|
-
def after_initialize
|
16
|
-
@text = ""
|
17
|
-
@x_factor = @y_factor = 1.0
|
18
|
-
@z_order = 0
|
19
|
-
@color = Gosu::Color.new "rgba(255,255,255,1.0)"
|
20
|
-
@size = 20
|
21
|
-
@font_family = Gosu::default_font_name
|
22
|
-
end
|
23
|
-
|
24
|
-
def font
|
25
|
-
@font ||= Gosu::Font.new(window, font_family, size)
|
26
|
-
end
|
27
|
-
|
28
|
-
def x
|
29
|
-
@x || (Game.width/2 - font.text_width(text)/2)
|
30
|
-
end
|
31
|
-
|
32
|
-
def y
|
33
|
-
@y || (Game.height/2 - font.height/2)
|
34
|
-
end
|
35
|
-
|
36
|
-
def bounds
|
37
|
-
Bounds.new x, y, x + width, y + height
|
38
|
-
end
|
39
|
-
|
40
|
-
def width
|
41
|
-
font.text_width(text) * x_factor
|
42
|
-
end
|
43
|
-
|
44
|
-
def height
|
45
|
-
font.height * y_factor
|
46
|
-
end
|
47
|
-
|
48
|
-
def contains?(x,y)
|
49
|
-
bounds.contains?(x,y)
|
50
|
-
end
|
51
|
-
|
52
|
-
def text
|
53
|
-
scene.instance_eval( "\"#{@text}\"" )
|
54
|
-
end
|
55
|
-
|
56
|
-
def draw
|
57
|
-
label_text = text
|
58
|
-
font.draw label_text, x, y, z_order, x_factor, y_factor, color
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
data/lib/templates/view.yaml.erb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
title:
|
2
|
-
model: metro::models::label
|
3
|
-
text: STARRY KNIGHT
|
4
|
-
x: 30
|
5
|
-
y: 50
|
6
|
-
z-order: 4
|
7
|
-
x-factor: 3
|
8
|
-
y-factor: 3
|
9
|
-
color: "rgba(255,255,0,0.0)"
|
10
|
-
logo:
|
11
|
-
model: metro::models::image
|
12
|
-
x: 540
|
13
|
-
y: 380
|
14
|
-
z-order: 4
|
15
|
-
path: "player.png"
|
16
|
-
color: "rgba(255,255,255,0.0)"
|
17
|
-
star: &star_default
|
18
|
-
model: star
|
19
|
-
x: 100
|
20
|
-
y: 400
|
21
|
-
path: "star.png"
|
22
|
-
width: 25
|
23
|
-
height: 25
|
24
|
-
tileable: false
|
25
|
-
star2:
|
26
|
-
<<: *star_default
|
27
|
-
x: 455
|
28
|
-
y: 333
|
29
|
-
star3:
|
30
|
-
<<: *star_default
|
31
|
-
x: 515
|
32
|
-
y: 40
|