pulo 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pulo.rb +28 -0
- data/lib/pulo/exceptions.rb +6 -0
- data/lib/pulo/figure/figure2d.rb +248 -0
- data/lib/pulo/figure/figure3d.rb +166 -0
- data/lib/pulo/formatting.rb +140 -0
- data/lib/pulo/frames/frame.rb +289 -0
- data/lib/pulo/frames/frame_cell.rb +83 -0
- data/lib/pulo/frames/frame_column.rb +149 -0
- data/lib/pulo/frames/frame_row.rb +87 -0
- data/lib/pulo/helpers.rb +1 -0
- data/lib/pulo/machine/hydraulics/pipe.rb +71 -0
- data/lib/pulo/machine/machines.rb +10 -0
- data/lib/pulo/machine/mechanics/moments_of_inertia.rb +64 -0
- data/lib/pulo/machine/steam/boiler.rb +61 -0
- data/lib/pulo/machine/steam/boiler_deaerator.rb +64 -0
- data/lib/pulo/machine/steam/deaerator.rb +37 -0
- data/lib/pulo/machine/steam/desuperheater.rb +29 -0
- data/lib/pulo/machine/steam/header.rb +20 -0
- data/lib/pulo/machine/steam/if97.rb +378 -0
- data/lib/pulo/machine/steam/steam_process.rb +27 -0
- data/lib/pulo/machine/steam/steam_turbine.rb +42 -0
- data/lib/pulo/machine/steam/water_steam.rb +229 -0
- data/lib/pulo/material/water.rb +34 -0
- data/lib/pulo/quantity/dimension.rb +63 -0
- data/lib/pulo/quantity/numeric_overloads.rb +217 -0
- data/lib/pulo/quantity/quantity.rb +285 -0
- data/lib/pulo/quantity/quantity_builder.rb +185 -0
- data/lib/pulo/quantity/quantity_definitions.rb +8 -0
- data/lib/pulo/quantity/quantity_definitions/area_volume.rb +73 -0
- data/lib/pulo/quantity/quantity_definitions/basic.rb +157 -0
- data/lib/pulo/quantity/quantity_definitions/electric.rb +22 -0
- data/lib/pulo/quantity/quantity_definitions/energy.rb +50 -0
- data/lib/pulo/quantity/quantity_definitions/fluids.rb +23 -0
- data/lib/pulo/quantity/quantity_definitions/force_power.rb +82 -0
- data/lib/pulo/quantity/quantity_definitions/rotation.rb +49 -0
- data/lib/pulo/quantity/quantity_definitions/value.rb +65 -0
- data/lib/pulo/quantity/quantity_definitions/velocity_acc_flow.rb +66 -0
- data/lib/pulo/quantity/quantity_groups/quantity_groups.rb +36 -0
- data/lib/pulo/quantity/unit.rb +45 -0
- data/lib/pulo/quantity_checker.rb +13 -0
- data/lib/pulo/tables/density.rb +10 -0
- data/lib/pulo/tables/melting_temperature.rb +9 -0
- data/lib/pulo/tables/specific_energy.rb +10 -0
- data/lib/pulo/tables/speed_of_sound.rb +9 -0
- data/lib/pulo/tables/tables.rb +104 -0
- data/lib/pulo/tables/tensile_strength.rb +10 -0
- data/lib/pulo/tables/yield_strength.rb +10 -0
- data/lib/pulo/version.rb +3 -0
- metadata +51 -3
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'descriptive_statistics'
|
2
|
+
|
3
|
+
module Pulo
|
4
|
+
class FrameColumn
|
5
|
+
|
6
|
+
attr_reader :name,:formula, :formatter, :column_class, :column_unit
|
7
|
+
attr_accessor :width
|
8
|
+
|
9
|
+
def initialize(name,parent_frame,hidden,&formula)
|
10
|
+
@name=name
|
11
|
+
@parent_frame=parent_frame
|
12
|
+
@formula=formula
|
13
|
+
@cells=[]
|
14
|
+
#@recalc_required=block_given?
|
15
|
+
@value_column=!block_given?
|
16
|
+
@standard_formatter=lambda {|v| v.to_s }
|
17
|
+
@formatter=@standard_formatter
|
18
|
+
@hidden=hidden
|
19
|
+
@width=3
|
20
|
+
@column_class=NilClass
|
21
|
+
@column_unit=NilClass
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_formula &formula
|
25
|
+
@formula=formula
|
26
|
+
#@recalc_required=true
|
27
|
+
@value_column=false
|
28
|
+
end
|
29
|
+
|
30
|
+
def column_number
|
31
|
+
@parent_frame.column_names[@name]
|
32
|
+
end
|
33
|
+
|
34
|
+
def column_class= (klass)
|
35
|
+
@column_class=klass
|
36
|
+
if @column_class.respond_to?(:quantity_name) and @formatter==@standard_formatter
|
37
|
+
@formatter=lambda {|q| q.to_s(nil,true)}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
def column_unit=(klass)
|
41
|
+
@column_unit=klass
|
42
|
+
end
|
43
|
+
def formatter= (lamb)
|
44
|
+
@formatter=lamb
|
45
|
+
end
|
46
|
+
def hidden?
|
47
|
+
@hidden
|
48
|
+
end
|
49
|
+
def hidden=value
|
50
|
+
@hidden=value
|
51
|
+
end
|
52
|
+
def name= new_name
|
53
|
+
if @parent_frame.column_names[new_name]
|
54
|
+
@name=new_name
|
55
|
+
else
|
56
|
+
@parent_frame.rename_column @name,new_name
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def append_row(cell)
|
61
|
+
@cells<<cell
|
62
|
+
end
|
63
|
+
def insert_row(row_no,cell)
|
64
|
+
@cells.insert(row_no,cell)
|
65
|
+
end
|
66
|
+
|
67
|
+
def values=(vals)
|
68
|
+
raise ArgumentError,"Wrong number of values given for column - need an array of #{@cells.count}" unless vals.count==@cells.count
|
69
|
+
vals.each_with_index do |val,index|
|
70
|
+
@cells[index].value=val
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def recalc with_timing=false
|
75
|
+
t_start=Time.now
|
76
|
+
|
77
|
+
@column_class=NilClass
|
78
|
+
@parent_frame.rows.each do |row|
|
79
|
+
begin
|
80
|
+
row[column_number].value=@formula.call(row)
|
81
|
+
row[column_number].unset_error
|
82
|
+
rescue Exception => e
|
83
|
+
#raise "Exception '#{e}' occured calculating column: #{@name} row: #{row.row_number}"
|
84
|
+
warn "Warning! Exception '#{e}' occured calculating column: #{@name} row: #{row.row_number}"
|
85
|
+
row[column_number].set_error
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
if with_timing
|
90
|
+
puts "Recalc column '#{@name}' in: #{((Time.now-t_start)*1000).to_i} ms."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def [](index)
|
95
|
+
raise IndexError,"No row number #{index} defined." unless @cells[index]
|
96
|
+
@cells[index]
|
97
|
+
end
|
98
|
+
|
99
|
+
def lookup(value)
|
100
|
+
(@cells.find_all {|cell| cell.value==value}).map {|cell| cell.row}
|
101
|
+
end
|
102
|
+
|
103
|
+
def map!(&block)
|
104
|
+
@cells.each {|cell| cell.value=block.call(cell.value)}
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_a
|
108
|
+
@cells.map {|cell| cell.value}
|
109
|
+
end
|
110
|
+
|
111
|
+
def value_column?
|
112
|
+
@value_column
|
113
|
+
end
|
114
|
+
|
115
|
+
def recalc_width
|
116
|
+
@width=@cells.take(30).map {|c| c.to_s.length}.max
|
117
|
+
@width||=0
|
118
|
+
@width=[@width,@name.length].max
|
119
|
+
@width=[@width,column_class.to_s.length+1].max
|
120
|
+
end
|
121
|
+
|
122
|
+
def to_s
|
123
|
+
"#{@name}: #{(@cells.map {|c| c.to_s}).join(', ')}"
|
124
|
+
end
|
125
|
+
def inspect
|
126
|
+
"Frame Column Object"
|
127
|
+
end
|
128
|
+
|
129
|
+
def descriptive_statistics
|
130
|
+
vals=self.to_a
|
131
|
+
if @column_class.respond_to?(:quantity_name)
|
132
|
+
vals=vals.map{|val| val.send(@column_unit.name).value}
|
133
|
+
end
|
134
|
+
stats=vals.descriptive_statistics
|
135
|
+
if @column_class.respond_to?(:quantity_name)
|
136
|
+
stats.map{|val|
|
137
|
+
|
138
|
+
if val[0]!=:number
|
139
|
+
[val[0],@column_class.new(val[1],@column_unit)]
|
140
|
+
else
|
141
|
+
[val[0],val[1]]
|
142
|
+
end
|
143
|
+
|
144
|
+
}.to_h
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Pulo
|
2
|
+
class FrameRow
|
3
|
+
attr_reader :cells
|
4
|
+
attr_accessor :row_number
|
5
|
+
def initialize(parent_frame, row_number)
|
6
|
+
@cells=[]
|
7
|
+
@parent_frame=parent_frame
|
8
|
+
@row_number=row_number
|
9
|
+
end
|
10
|
+
|
11
|
+
def append_column(cell)
|
12
|
+
@cells<<cell
|
13
|
+
end
|
14
|
+
|
15
|
+
def delete_column(index)
|
16
|
+
@cells.delete_at index
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](column)
|
20
|
+
if column.is_a?(Integer)
|
21
|
+
raise IndexError,"No column number #{column} defined." unless @cells[column]
|
22
|
+
@cells[column]
|
23
|
+
else
|
24
|
+
@parent_frame[column][@row_number]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def previous_rows
|
29
|
+
Enumerator.new do |y|
|
30
|
+
for i in (0..(@row_number-1)).reverse_each
|
31
|
+
y.yield @parent_frame.rows[i]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def next_rows
|
37
|
+
Enumerator.new do |y|
|
38
|
+
for i in (@row_number+1)..@parent_frame.row_count-1
|
39
|
+
y.yield @parent_frame.rows[i]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def previous_row
|
45
|
+
if @row_number>0
|
46
|
+
@parent_frame.rows[@row_number-1]
|
47
|
+
else
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def next_row
|
53
|
+
if @row_number<@parent_frame.row_count
|
54
|
+
@parent_frame.rows[@row_number+1]
|
55
|
+
else
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
"row #{@row_number}:".ljust(9,' ') + " #{((@cells.select {|s| !s.column.hidden?}).map {|c| c.to_s}).join(' ')}"
|
62
|
+
end
|
63
|
+
def inspect
|
64
|
+
"Frame Row Object"
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_a
|
68
|
+
@cells.map {|cell| cell.value}
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_a_values
|
72
|
+
value_cells.map {|cell| cell.value}
|
73
|
+
end
|
74
|
+
|
75
|
+
def value_cells
|
76
|
+
@cells.find_all { |cell| cell.value_column?}
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_h
|
80
|
+
Hash[@parent_frame.column_names.keys.to_a.zip(to_a)]
|
81
|
+
end
|
82
|
+
|
83
|
+
def first_row?
|
84
|
+
@row_number==0
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/pulo/helpers.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# encoding: utf-8
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Pulo
|
2
|
+
|
3
|
+
class PipeTypes
|
4
|
+
attr_reader :pipe_types
|
5
|
+
def initialize
|
6
|
+
pipe_groups={
|
7
|
+
uPvc: {Chw: 150, density: Density.kilograms_per_cubic_meter(1800), unit_length: Length.meters(6)}
|
8
|
+
}
|
9
|
+
@pipe_types={
|
10
|
+
class6_160: {group: :uPvc, od: Length.millimeters(160.0), id: Length.millimeters(153.6), unit_cost: Value.dollars(50)},
|
11
|
+
class6_200: {group: :uPvc, od: Length.millimeters(200.0), id: Length.millimeters(192.2), unit_cost: Value.dollars(78)},
|
12
|
+
class6_250: {group: :uPvc, od: Length.millimeters(250.0), id: Length.millimeters(242.0), unit_cost: Value.dollars(105)},
|
13
|
+
class6_315: {group: :uPvc, od: Length.millimeters(315.0), id: Length.millimeters(302.6), unit_cost: Value.dollars(232)},
|
14
|
+
class6_355: {group: :uPvc, od: Length.millimeters(355.0), id: Length.millimeters(341.0), unit_cost: Value.dollars(326)},
|
15
|
+
class6_400: {group: :uPvc, od: Length.millimeters(400.0), id: Length.millimeters(384.4), unit_cost: Value.dollars(440)},
|
16
|
+
class6_450: {group: :uPvc, od: Length.millimeters(450.0), id: Length.millimeters(428.8), unit_cost: Value.dollars(610)},
|
17
|
+
class6_500: {group: :uPvc, od: Length.millimeters(500.0), id: Length.millimeters(476.4), unit_cost: Value.dollars(750)}
|
18
|
+
}
|
19
|
+
@pipe_types.values.each do |pt|
|
20
|
+
pt.merge!(pipe_groups[pt[:group]])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
class Pipeline
|
27
|
+
|
28
|
+
attr_reader :inside_cylinder,:outside_cylinder,:length
|
29
|
+
attr_reader :wall_thickness, :wall_area, :wall_volume, :mass
|
30
|
+
attr_reader :pipe_type
|
31
|
+
attr_reader :wall_density
|
32
|
+
attr_reader :inlet_pressure,:outlet_pressure, :flow
|
33
|
+
attr_reader :friction_gradient, :static_head, :friction_head, :total_head, :flow_velocity, :hydraulic_power
|
34
|
+
attr_reader :cost
|
35
|
+
|
36
|
+
def initialize(args)
|
37
|
+
|
38
|
+
@pipe_type_ref=args[:pipe]
|
39
|
+
@pipe_type=PipeTypes.new().pipe_types[@pipe_type_ref]
|
40
|
+
|
41
|
+
@length=args[:length]
|
42
|
+
@cost=@length*@pipe_type[:unit_cost]/@pipe_type[:unit_length]
|
43
|
+
@inside_cylinder=Cylinder.new(diameter: @pipe_type[:id], length: @length)
|
44
|
+
@outside_cylinder=Cylinder.new(diameter: @pipe_type[:od], length: @length)
|
45
|
+
@wall_thickness=@outside_cylinder.radius-@inside_cylinder.radius
|
46
|
+
@wall_area=@outside_cylinder.area-@inside_cylinder.area
|
47
|
+
@wall_volume=@outside_cylinder.volume-@inside_cylinder.volume
|
48
|
+
@mass=@wall_volume*@pipe_type[:density]
|
49
|
+
|
50
|
+
args[:static_head] ? @static_head=args[:static_head] : @static_head=Length.meters(0)
|
51
|
+
args[:inlet_pressure] ? @inlet_pressure=args[:inlet_pressure] : @inlet_pressure=Pressure.pascals(0)
|
52
|
+
args[:outlet_pressure] ? @outlet_pressure=args[:outlet_pressure] : @outlet_pressure=Pressure.pascals(0)
|
53
|
+
@pressure_head=(@outlet_pressure-@inlet_pressure)/(Water.standard_density*Acceleration.standard_gravity)
|
54
|
+
end
|
55
|
+
|
56
|
+
def flow=(val)
|
57
|
+
@flow=val
|
58
|
+
@flow_velocity=@flow/inside_cylinder.area
|
59
|
+
head_for_flow()
|
60
|
+
@hydraulic_power=((@flow*Water.standard_density)*Acceleration.standard_gravity)*@total_head
|
61
|
+
end
|
62
|
+
|
63
|
+
def head_for_flow()
|
64
|
+
k=(@pipe_type[:Chw]**1.85)*@inside_cylinder.face.diameter.meters.value**4.87
|
65
|
+
@friction_gradient=Dimensionless.n(10.67*@flow.cubic_meter_per_second.value**1.85/k)
|
66
|
+
@friction_head=@length * @friction_gradient
|
67
|
+
@total_head=@friction_head+@static_head+@pressure_head
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative './steam/water_steam'
|
2
|
+
require_relative './steam/boiler'
|
3
|
+
require_relative './steam/deaerator'
|
4
|
+
require_relative './steam/boiler_deaerator'
|
5
|
+
require_relative './steam/desuperheater'
|
6
|
+
require_relative './steam/header'
|
7
|
+
require_relative './steam/steam_process'
|
8
|
+
require_relative './steam/steam_turbine'
|
9
|
+
|
10
|
+
require_relative './mechanics/moments_of_inertia'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Pulo
|
2
|
+
class MomentOfInertia
|
3
|
+
def self.point_mass(mass, distance)
|
4
|
+
mass*distance**2
|
5
|
+
end
|
6
|
+
|
7
|
+
#rod around its mid point
|
8
|
+
def self.rod(mass, length)
|
9
|
+
(mass*distance**2)/12.0
|
10
|
+
end
|
11
|
+
|
12
|
+
#rod around its mid point
|
13
|
+
def self.rod_end(mass, length)
|
14
|
+
(mass*length**2)/3.0
|
15
|
+
end
|
16
|
+
|
17
|
+
#hoop
|
18
|
+
def self.hoop(mass, radius)
|
19
|
+
(mass*radius**2)/2.0
|
20
|
+
end
|
21
|
+
|
22
|
+
#disc
|
23
|
+
def self.disc(mass, radius)
|
24
|
+
(mass*radius**2)/4.0
|
25
|
+
end
|
26
|
+
|
27
|
+
#cylindrical shell on its axis
|
28
|
+
def self.cylindrical_shell(mass, radius)
|
29
|
+
(mass*radius**2)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.cylinder(mass, radius, height)
|
33
|
+
(3*radius**2+height**2)*mass/12.0
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.tube(mass, inner_radius,outer_radius)
|
37
|
+
(inner_radius**2+outer_radius**2)*mass/2.0
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.spherical_shell(mass, radius)
|
41
|
+
(2*mass*radius**2)/3.0
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.sphere(mass, radius)
|
45
|
+
(2*mass*radius**2)/5.0
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.thick_spherical_shell(mass, inner_radius,outer_radius)
|
49
|
+
((outer_radius**5-inner_radius**5)/(outer_radius**3-inner_radius**3))*(2*mass/5)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.cone(mass, radius, height)
|
53
|
+
(radius**2+4*height**2)*(3*mass/20)
|
54
|
+
end
|
55
|
+
|
56
|
+
#cuboid or plate of arbitrary depth (in direction of axis of rotation)
|
57
|
+
def self.cuboid(mass, width, height)
|
58
|
+
(height**2+width**2)*(mass/12)
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Pulo
|
4
|
+
module Steam
|
5
|
+
class Boiler
|
6
|
+
attr_reader :feedwater, :steam, :blowdown
|
7
|
+
attr_reader :blowdown_rate, :combustion_efficiency
|
8
|
+
attr_reader :boiler_power, :fuel_power
|
9
|
+
|
10
|
+
def initialize(feedwater_pressure: nil,blowdown_rate: nil,combustion_efficiency:nil,steam_pressure: nil,
|
11
|
+
steam_temperature: nil,fuel_power: nil,
|
12
|
+
steam_massflow: nil,feedwater_massflow: nil)
|
13
|
+
|
14
|
+
raise "Need all parameters" unless
|
15
|
+
feedwater_pressure && blowdown_rate &&
|
16
|
+
combustion_efficiency && steam_pressure &&
|
17
|
+
(steam_temperature || fuel_power) &&
|
18
|
+
(steam_massflow || feedwater_massflow)
|
19
|
+
|
20
|
+
#steam_massflow=steam_massflow
|
21
|
+
@blowdown_rate=blowdown_rate
|
22
|
+
@combustion_efficiency=combustion_efficiency
|
23
|
+
@steam_temperature=steam_temperature
|
24
|
+
@feedwater_pressure=feedwater_pressure
|
25
|
+
@steam_pressure=steam_pressure
|
26
|
+
@fuel_power=fuel_power
|
27
|
+
#feedwater_massflow=feedwater_massflow
|
28
|
+
|
29
|
+
@blowdown=WaterSteam.new(pressure: @steam_pressure, quality: Dimensionless.new(0))
|
30
|
+
if steam_massflow
|
31
|
+
feedwater_massflow=steam_massflow/(1-@blowdown_rate)
|
32
|
+
else
|
33
|
+
steam_massflow=feedwater_massflow*(1-@blowdown_rate)
|
34
|
+
end
|
35
|
+
|
36
|
+
@blowdown.mass_flow=feedwater_massflow*@blowdown_rate
|
37
|
+
#@blowdown_power=@blowdown.specific_enthalpy*@blowdown_massflow
|
38
|
+
|
39
|
+
@feedwater=WaterSteam.new(pressure: @feedwater_pressure, quality: Dimensionless.new(0))
|
40
|
+
@feedwater.mass_flow=feedwater_massflow
|
41
|
+
#@feedwater_power=@feedwater.specific_enthalpy*@feedwater_massflow
|
42
|
+
|
43
|
+
|
44
|
+
if @steam_temperature
|
45
|
+
@steam=WaterSteam.new(pressure: @steam_pressure, temperature: @steam_temperature)
|
46
|
+
@steam.mass_flow=steam_massflow
|
47
|
+
#@steam_power=@steam.specific_enthalpy*@steam_massflow
|
48
|
+
@boiler_power=@steam.energy_flow + @blowdown.energy_flow - @feedwater.energy_flow
|
49
|
+
@fuel_power=@boiler_power/@combustion_efficiency
|
50
|
+
else
|
51
|
+
@boiler_power=@fuel_power*@combustion_efficiency
|
52
|
+
steam_power=@boiler_power-@blowdown.energy_flow+@feedwater.energy_flow
|
53
|
+
specific_enthalpy=steam_power/steam_massflow
|
54
|
+
@steam=WaterSteam.new(pressure: @steam_pressure, specific_enthalpy: specific_enthalpy)
|
55
|
+
@steam.mass_flow=steam_massflow
|
56
|
+
raise "Boiler not boiling!" if @steam.if97_region=="1"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|