lens_protocol 0.1.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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.rubocop.yml +98 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +106 -0
- data/Guardfile +42 -0
- data/LICENSE.txt +21 -0
- data/README.md +69 -0
- data/Rakefile +6 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/examples/images/R360_1.png +0 -0
- data/examples/oma/R1000_1.oma +213 -0
- data/examples/oma/R1000_2.oma +213 -0
- data/examples/oma/R1000_3.oma +217 -0
- data/examples/oma/R360_1.oma +78 -0
- data/examples/oma/R360_2.oma +75 -0
- data/examples/oma/R360_3.oma +276 -0
- data/examples/oma/TRCFMT6.oma +28 -0
- data/examples/public/styles.css +22 -0
- data/examples/svg.rb +10 -0
- data/examples/views/index.erb +26 -0
- data/lens_protocol.gemspec +33 -0
- data/lib/lens_protocol.rb +18 -0
- data/lib/lens_protocol/errors.rb +10 -0
- data/lib/lens_protocol/oma.rb +14 -0
- data/lib/lens_protocol/oma/formatter.rb +22 -0
- data/lib/lens_protocol/oma/message.rb +138 -0
- data/lib/lens_protocol/oma/parser.rb +24 -0
- data/lib/lens_protocol/oma/record.rb +19 -0
- data/lib/lens_protocol/oma/type/base.rb +97 -0
- data/lib/lens_protocol/oma/type/integer.rb +15 -0
- data/lib/lens_protocol/oma/type/numeric.rb +24 -0
- data/lib/lens_protocol/oma/type/r.rb +17 -0
- data/lib/lens_protocol/oma/type/text.rb +8 -0
- data/lib/lens_protocol/oma/type/trcfmt.rb +30 -0
- data/lib/lens_protocol/oma/types.rb +84 -0
- data/lib/lens_protocol/svg.rb +45 -0
- data/lib/lens_protocol/version.rb +3 -0
- metadata +213 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
REQ=FIL
|
2
|
+
DO=B
|
3
|
+
BEVM=0.00;0.00
|
4
|
+
BEVP=4;4
|
5
|
+
CIRC=151.860;151.860
|
6
|
+
DBL=17.00
|
7
|
+
ETYP=3
|
8
|
+
FCSGIN=1.50;1.50
|
9
|
+
FCSGUP=4.00;4.00
|
10
|
+
FPINB=0.00;0.00
|
11
|
+
FTYP=3
|
12
|
+
GDEPTH=0.50;0.50
|
13
|
+
GWIDTH=0.60;0.60
|
14
|
+
HBOX=53.99;53.99
|
15
|
+
NPD=34.00;34.00
|
16
|
+
IPD=34.00;34.00
|
17
|
+
SEGHT=22.00;22.00
|
18
|
+
OCHT=22.00;22.00
|
19
|
+
PINB=0.20;0.20
|
20
|
+
POLISH=1
|
21
|
+
TRCFMT=6;360;E;R;F
|
22
|
+
R=6167514141436D71764D2B7958762F524C337855574A4939485372724B525553742B3733737151776F5A554871777046704B39455452706378337A4744544C4F48397961556D33657938627A63394D6B4E415A766E7A46626F4B462B586962644874692F435071432F445670717044755936734274304E797536472F356D4E44305474302F56584D4D75614441743566346662484B474C6A4C314E67433765703562424B7474584D495945753730534A6A45776A4575384A783930624F326D782B67715A6E6F466A4E6D51724C325A3334467945614646615A2B423264793066505A4D6B64585968584E3259504E6744713235574D634B353233494A304D746B5865347A346E776D6E6B6136635649576357475A32454133634A68624D2F63616C494F38724B4C7556584F7176634A4B567768336A387762767430422F636633766537502F31784173694F366173424134695A727970324249757657495051756C5364684F4B327043387A75344C534367544F54424A6F42384B41356449674A506B523678697146796B52464230686E4142594C684E2B73385059636D5A4E675362494F454542514D745A664A75395145743957674C4149754E32737A42494872384B302F376C375965792F364C7131597661416C4D4E3954345853595138685964624F617571674E7843554C4634736458635469485272354D2B5533712F6D477A6E656F6B5673654B7245517A675754625248474A667A3341593242576C6E733169466D6A53516F485335586863597854676274435955666B376A36466E32576136464D6572736E44516874374379656D44615441782F314A47377A526E716777504C506F4D6F6D422F54766D63324B4757306933746C4750386E4A614A684D6549636E504145433761534A347A35516353666A50442F4448385855764431424A4456304D387A6E4871636C32614B346B4B7754444D39317264514B3148526A6A695A69773942774E69484878583246475641582F4F2B752F666467375574784E7A6B7159573841437177327741304D3976322B3032694B66755A7A534856576E4E656941382F384148714F76494B646136692B53634F6B4F6A6A7478777975697767724752386833613677314C444D666255443157707544354C795867554D3651637274463963784D497547674374387563334B48786F57567738472F484A3961625731506B624749473173524D4C346255556D4F684678766F75434E637879314C314F4E703331445530655979726F654C357849444B5937426C51415872464A564A336F6B4A32632B4A76587A2B4576552F67446944457749665177735A34596556306253422F567151546B6A786A584C6D6574336D714B4775477A61697063326F75332B617637567A3753424C567835396F667878646741666F5854657A473949306F5A31485A7057314B35556331762F435743705A38784C395569316E34575936393757612F336C69416B7447386D6D55336E5465486F6134344379696A617073537078716A344D344678454F755763375336635A4E6454502B476A543570415935633037396A4D69493636713931445033472B5669347A5833306B797565342B5A486D646B4A69366349694275506A49786755723849494438746B5258303751644F2F496F6F556A716B6E735455416E472F526D6E41764332434C515257704D7A4D6930454D6E5866574B636E6D6F487552504A63374D5235535744396D444D54393274786655753949436E3045435761755933386E374663553436526F51376564687235346431615166507044786A6552756F6468303144745267647A4A7661506630596D534270636E486137723769317036526D6D7637574A61624747516965796A6C32424D494A785373632F3762746D302F745A6D6237723974675A2B6D6F515A7A6B4C53536A45576F385A356A324D4D58446E586C2B316B5A7462497174653875726F7A7773724A43386F7A6D595259443273346750346F4A5A374B3970364A636D75644D665633496762554B706F6E716C56505469497076762F71494C375231356349582B322F3538494732736D35427236657044572F4C7759616D51514867794D55636B
|
23
|
+
TRCFMT=6;360;E;L;F
|
24
|
+
R=61675141414D4E6C4D58334355662F61433866447949556F7A747534612B36753438664A634F5967394F7137657A625A5052714652573954624B5572744852493458362B756951372F544A6441424673366C2F464B3143714E62664B30396D583939512B54346C644E3967563173657948302F7938614D62586B67756553396E3171474D6C54766E48666844334E3070365A4E414C6441694E4D685A6E43373851594E4B495533794C37553331434B4E44585251426C46763063484B6248437476664B58794E6A75584362634665396A596C30786A3366596C4C5466414D6F5A706F73536F484D44563072455A7663352F7334594954494B5A432B635237684941427874526633746430757571573058762B48615432736C2F4366397642343174574959536B575A4C366E2B634E6A706468722B46357468573068637A6F396845705472516C43304D717077776C683535646F4C514E31625041704D3175724D4F6937483052594178517734674645754E5441666B307056695A4D4E2B73467A584A5434436A654E7961676D6C4E3843694E6C674A35316A544E33566E5756554E6645634C4F7059752F73314E53445A7869733973626970642F593277635751467975627175394D5954764E666977653655704D514A6D5038537879372F726973593570435969303245722F424D7A525A564B6262437356314D646134446C4A38316F4D45614C617044656A2B4F4F6C7550774D70704E5245696D5862587346505159335549645872564864624375302B30333353654F574443336E6C6E336F6B4E506A45485739686D48564F493454456B6B65786F4C6C506C69394F454C2B476D53536832757A526B62795550525975697A5673417559763638655A775548556245555A6C4753594436646770733659766B726C524532793278644C3451556F55534368305678442B577149686D31705843764D4E4656616848643157336641514F57344E6D335452624B47594A786C6F326A4A46344557565A5A452F425844655230396555414968424567736B474E794B657731765A78384F7949646443486A726670457367337A4F6F734A677755685765436E466A51763571413069696F56507468726F67466568583668457351754635507A526E677047574A746A5059652F446E79764476386530685869346A744E4F4D377657394B744B696D6E76324E744C71387358794F6535494B723261773845746E766D78626867367A43685342767A74585A5238337838796A7367344B7675304B535663547763656A5777735A4277457A482B58484966416F7366584D5A363065705053697746304F3359317349394C75693149534F396B58537577684A41435A6D767A71655167304D6456414C36476433564B6A5853355658547A7071793054307A69452F5235483636326C763151636B436F36724B44502B4D505163446567486B5744502B4E702B426175677A6F31564742353271634441777741494168566E71307356694153474E732B2F66644D4237544239576F797A4444584F55665A4C717068796F6E536556467448376D70482F4E786669485439483878465950346265665061332F624661466D2B797359616B546450555255785A67487869443872784F385678314C6B56303035737045776E39537278334A513077765977715150387A5555793234426C3355567A356977497331794A494762502B73574148417255705254566575697A5149536A347538314C524E6974576F5356363742466C426E7473324D624465336869684D36394939652F53596C4255696A6D4F3949706959336D377A6137425933716D504E694561395A71676C463434776E48574F74336D6E4730697476363948536F324752336F7352474F545266687A616C6E6C4B68544C613746674B443639796A6A2F376934326630547153366F56595A747264386A6844687963657773564E6A787873386350665851664F6A2B4C636C3358796E7A69726E45437071785A484332714B305653506A452F676670796F4547756E4756723946674F64706779304359496F69315A576B3936522F717457366567336B51344C4274646962562F4676796D6C79637274356865364251
|
25
|
+
VBOX=36.00;36.00
|
26
|
+
VEN=NDKVCA
|
27
|
+
HVER=4.0
|
28
|
+
FED=57.18;57.18
|
@@ -0,0 +1,22 @@
|
|
1
|
+
body {
|
2
|
+
display: grid;
|
3
|
+
grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
|
4
|
+
grid-gap: 1em;
|
5
|
+
}
|
6
|
+
|
7
|
+
.lenses-container {
|
8
|
+
vertical-align: top;
|
9
|
+
white-space: nowrap;
|
10
|
+
text-align: center;
|
11
|
+
}
|
12
|
+
|
13
|
+
.lens {
|
14
|
+
width: 200px;
|
15
|
+
display: inline-block;
|
16
|
+
padding: 10px;
|
17
|
+
}
|
18
|
+
|
19
|
+
.lens svg {
|
20
|
+
stroke: black;
|
21
|
+
fill: #eee;
|
22
|
+
}
|
data/examples/svg.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'lens_protocol'
|
3
|
+
|
4
|
+
get '/' do
|
5
|
+
files_and_messages = Dir['examples/oma/*.oma'].map do |file|
|
6
|
+
[File.basename(file), LensProtocol::OMA.parse(File.read(file))]
|
7
|
+
end
|
8
|
+
|
9
|
+
erb :index, locals: {files_and_messages: files_and_messages}
|
10
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<link rel="stylesheet" href="styles.css">
|
5
|
+
<title>SVG Demo</title>
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<% files_and_messages.each do |(filename, message)| %>
|
9
|
+
<div class="lenses-container">
|
10
|
+
<div class="filename"><%= filename %></div>
|
11
|
+
|
12
|
+
<% if (svgs = message.to_svg).any? %>
|
13
|
+
<% svgs.map do |svg| %>
|
14
|
+
<div class="lens">
|
15
|
+
<%= svg %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
<% else %>
|
19
|
+
<div>
|
20
|
+
Could not recognize tracing data.
|
21
|
+
</div>
|
22
|
+
<% end %>
|
23
|
+
</div>
|
24
|
+
<% end %>
|
25
|
+
</body>
|
26
|
+
</html>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "lens_protocol/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "lens_protocol"
|
7
|
+
spec.version = LensProtocol::VERSION
|
8
|
+
spec.authors = ["Emmanuel Nicolau"]
|
9
|
+
spec.email = ["emmanicolau@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = %q{LensProtocol is a Ruby parser and builder for the OMA protocol.}
|
12
|
+
spec.description = %q{A Ruby parser and builder for the OMA protocol (a.k.a. Data Communication Standard) that was developed by the Lens Processing & Technology Division of The Vision Council for interconnection of optical laboratory equipment.}
|
13
|
+
spec.homepage = "https://github.com/eeng/lens_protocol"
|
14
|
+
|
15
|
+
# Specify which files should be added to the gem when it is released.
|
16
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
17
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
18
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_dependency 'activesupport', '>= 4.0'
|
25
|
+
spec.add_dependency 'nokogiri'
|
26
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
spec.add_development_dependency "guard-rspec"
|
30
|
+
spec.add_development_dependency 'pry'
|
31
|
+
spec.add_development_dependency 'pry-byebug'
|
32
|
+
spec.add_development_dependency 'sinatra'
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'lens_protocol/version'
|
5
|
+
require 'lens_protocol/errors'
|
6
|
+
require 'lens_protocol/oma/record'
|
7
|
+
require 'lens_protocol/oma/message'
|
8
|
+
require 'lens_protocol/oma/type/base'
|
9
|
+
require 'lens_protocol/oma/type/text'
|
10
|
+
require 'lens_protocol/oma/type/integer'
|
11
|
+
require 'lens_protocol/oma/type/numeric'
|
12
|
+
require 'lens_protocol/oma/type/trcfmt'
|
13
|
+
require 'lens_protocol/oma/type/r'
|
14
|
+
require 'lens_protocol/oma/types'
|
15
|
+
require 'lens_protocol/oma/parser'
|
16
|
+
require 'lens_protocol/oma/formatter'
|
17
|
+
require 'lens_protocol/oma'
|
18
|
+
require 'lens_protocol/svg'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module LensProtocol
|
2
|
+
module OMA
|
3
|
+
class Formatter
|
4
|
+
# Generates the OMA string from a Message
|
5
|
+
def format message, line_separator: "\r\n", start_of_message: '', end_of_message: '', **opts
|
6
|
+
[
|
7
|
+
start_of_message,
|
8
|
+
format_lines(message, **opts).join(line_separator),
|
9
|
+
line_separator,
|
10
|
+
end_of_message
|
11
|
+
].join
|
12
|
+
end
|
13
|
+
|
14
|
+
def format_lines message, types: {}
|
15
|
+
types = TYPES.merge(types)
|
16
|
+
message.records.values.flat_map do |record|
|
17
|
+
types[record.label].format(record, message)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module LensProtocol
|
2
|
+
module OMA
|
3
|
+
class Message
|
4
|
+
attr_reader :records
|
5
|
+
|
6
|
+
# Builds a message from a hash of record labels to record value.
|
7
|
+
def self.from_hash hash
|
8
|
+
hash.reduce new do |message, (label, value)|
|
9
|
+
message.add_record(label, value)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize records: {}, context: {}
|
14
|
+
@records = records
|
15
|
+
@context = context
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_record label, value
|
19
|
+
@records[label] ||= Record.new(label: label, value: value)
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_record_or_insert_values label, values
|
24
|
+
@records[label] ||= Record.new(label: label, value: [])
|
25
|
+
@records[label].value << values
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_record_or_concat_values label, values
|
30
|
+
@records[label] ||= Record.new(label: label, value: [])
|
31
|
+
@records[label].value.concat values
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_record_side_values label, side, values
|
36
|
+
@records[label] ||= Record.new(label: label, value: [[], []])
|
37
|
+
@records[label].value[side].concat values
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def set_context key, value
|
42
|
+
@context[key] = value
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def value_of label, default = nil
|
47
|
+
if include? label
|
48
|
+
@records[label].value
|
49
|
+
else
|
50
|
+
default
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns +true+ if the message contains a record with the given label
|
55
|
+
def include? label
|
56
|
+
@records.key? label
|
57
|
+
end
|
58
|
+
|
59
|
+
def empty?
|
60
|
+
@records.empty?
|
61
|
+
end
|
62
|
+
|
63
|
+
def context key
|
64
|
+
@context[key]
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_hash
|
68
|
+
Hash[*@records.flat_map { |label, record| [label, record.value] }]
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the "R" reconds decoded radiuses according to the tracing format.
|
72
|
+
def radius_data
|
73
|
+
return [] unless value_of('TRCFMT') && value_of('R')
|
74
|
+
[0, 1].map do |side|
|
75
|
+
format_number, = value_of('TRCFMT')[side]
|
76
|
+
case format_number.to_i
|
77
|
+
when 0 # side not present
|
78
|
+
[]
|
79
|
+
when 1 # ASCII format
|
80
|
+
value_of('R')[side]
|
81
|
+
else # unknown format
|
82
|
+
return []
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Converts the "R" record values to polar coordinates.
|
88
|
+
def tracing_in_polar_coordinates
|
89
|
+
radius_data.map { |radiuses| radiuses_to_polar radiuses }
|
90
|
+
end
|
91
|
+
|
92
|
+
def radiuses_to_polar radiuses
|
93
|
+
radiuses.map.with_index { |r, i| [i * 2 * Math::PI / radiuses.size, r] }
|
94
|
+
end
|
95
|
+
|
96
|
+
# Converts the "R" record values to rectangular coordinates.
|
97
|
+
def tracing_in_rectangular_coordinates
|
98
|
+
radius_data.map { |radiuses| radiuses_to_rectangular radiuses }
|
99
|
+
end
|
100
|
+
|
101
|
+
def radiuses_to_rectangular radiuses
|
102
|
+
radiuses_to_polar(radiuses).map { |(a, r)| [r * Math.cos(a), r * Math.sin(a)].map { |v| v.round 2 } }
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns an array of SVG strings, one for each side. If the tracing format is not recognized
|
106
|
+
# or there is no tracing data, returns an empty array.
|
107
|
+
def to_svg **opts
|
108
|
+
SVG.from_message self, **opts
|
109
|
+
end
|
110
|
+
|
111
|
+
# Similarly to +Hash#merge+ returns a new message containing the records of +this+ and the records of +other+
|
112
|
+
# keeping the ones in +other+ if the labels colides.
|
113
|
+
def merge other
|
114
|
+
Message.new records: @records.merge(other.records)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns a new message without the records of the given labels.
|
118
|
+
# @param labels [Array]
|
119
|
+
def except labels
|
120
|
+
Message.new records: @records.reject { |label, _| labels.include? label }
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns a new message with only the records of the given labels.
|
124
|
+
# @param labels [Array]
|
125
|
+
def only labels
|
126
|
+
Message.new records: @records.slice(*labels)
|
127
|
+
end
|
128
|
+
|
129
|
+
def remove_empty_records
|
130
|
+
Message.new records: @records.reject { |_, r| r.empty? }
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_s
|
134
|
+
OMA.format self
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module LensProtocol
|
2
|
+
module OMA
|
3
|
+
class Parser
|
4
|
+
def parse oma_str, types: {}
|
5
|
+
types = TYPES.merge(types)
|
6
|
+
normalize_line_endings(oma_str)
|
7
|
+
.split("\n")
|
8
|
+
.reduce(Message.new) { |message, line| parse_line line, message, types }
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def parse_line line, message, types
|
14
|
+
raise ParsingError.new('The label separator is missing', line) unless line.include?('=')
|
15
|
+
label, = line.split('=')
|
16
|
+
types[label].parse(line, message)
|
17
|
+
end
|
18
|
+
|
19
|
+
def normalize_line_endings str
|
20
|
+
str.to_s.gsub /\r\n?/, "\n"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module LensProtocol
|
2
|
+
module OMA
|
3
|
+
class Record
|
4
|
+
attr_reader :label
|
5
|
+
|
6
|
+
# May hold a single value, an array of values (on multi-value and chiral records), or an array of array of values (in R records for example)
|
7
|
+
attr_reader :value
|
8
|
+
|
9
|
+
def initialize label:, value:
|
10
|
+
@label = label
|
11
|
+
@value = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def empty?
|
15
|
+
Array(value).select(&:present?).empty?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module LensProtocol
|
2
|
+
module OMA
|
3
|
+
module Type
|
4
|
+
class Base
|
5
|
+
def initialize mode: :single_value
|
6
|
+
@mode = mode
|
7
|
+
end
|
8
|
+
|
9
|
+
# Given a line and a message produces a new message with the record(s) corresponding to that line added to the message
|
10
|
+
# @return [Message]
|
11
|
+
def parse line, message
|
12
|
+
label, data = label_and_data line
|
13
|
+
case @mode
|
14
|
+
when :single_value
|
15
|
+
message.add_record label, parse_value(data)
|
16
|
+
when :array_of_values
|
17
|
+
message.add_record_or_concat_values label, parse_values(data)
|
18
|
+
when :chiral
|
19
|
+
message.add_record label, parse_chiral(data)
|
20
|
+
when :matrix_of_values
|
21
|
+
message.add_record_or_insert_values label, parse_values(data)
|
22
|
+
else
|
23
|
+
raise ArgumentError, "Mode #{@mode} not supported"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array of lines or a single one]
|
28
|
+
def format record, _message
|
29
|
+
case @mode
|
30
|
+
when :single_value
|
31
|
+
format_line record.label, [format_value(record.value)]
|
32
|
+
when :array_of_values
|
33
|
+
format_line record.label, format_values(record.value)
|
34
|
+
when :chiral
|
35
|
+
format_line record.label, format_chiral(record.value)
|
36
|
+
when :matrix_of_values
|
37
|
+
record.value.map do |value|
|
38
|
+
format_line record.label, format_values(value)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
raise ArgumentError, "Mode #{@mode} not supported"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def label_and_data line
|
48
|
+
label, data = line.split('=', -1)
|
49
|
+
[label, data]
|
50
|
+
end
|
51
|
+
|
52
|
+
def label_and_values line
|
53
|
+
label, data = label_and_data line
|
54
|
+
[label, parse_values(data)]
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_values data
|
58
|
+
data.split(';', -1).map { |value| parse_value value }
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_value value
|
62
|
+
value if value != '?'
|
63
|
+
end
|
64
|
+
|
65
|
+
def parse_chiral values
|
66
|
+
make_chiral parse_values values
|
67
|
+
end
|
68
|
+
|
69
|
+
def make_chiral values
|
70
|
+
if values.size <= 1
|
71
|
+
[values[0], values[0]]
|
72
|
+
else
|
73
|
+
values[0..1]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def format_line label, values
|
78
|
+
"#{label}=#{values.join(';')}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def format_value value
|
82
|
+
value
|
83
|
+
end
|
84
|
+
|
85
|
+
def format_values values
|
86
|
+
values = values.is_a?(Array) ? values : [values]
|
87
|
+
values.map { |v| format_value(v) }
|
88
|
+
end
|
89
|
+
|
90
|
+
def format_chiral value
|
91
|
+
return [] if Array(value).select(&:present?).empty?
|
92
|
+
make_chiral format_values value
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|