graphvizml 0.6.3 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/graphvizml.rb +107 -103
  4. data.tar.gz.sig +0 -0
  5. metadata +47 -47
  6. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68960c6facef21cc3467b32f8089e6c3a3202cfc98b818d176e955ef08cc4ec4
4
- data.tar.gz: 466ed1b061681333f0b8000637c5a69aca59e67d90c30a2bd00c4b9a087ceb99
3
+ metadata.gz: 7ff946ca6dcb3ec1f3acd62e8da4205acb9c91a3e9702b86bd3ed79ad6a19fb2
4
+ data.tar.gz: 6d252b72c6b334382dc460b62f7dd1e015d024ce8a7ad1311db03adb7758122b
5
5
  SHA512:
6
- metadata.gz: 8e1c3402e21cde24951767273cb4edf3e02cb1ed1861fea5cb41e29c6bdf4429399c1afe02b9b53c3adca7a0839d11bb9b43adf2297012843596caab1562d74c
7
- data.tar.gz: a3b10bc32eee08b209533cfc76ecb342965f0b56917f6a25b2de1a551c0439d5a4ad12c6ef09df75aadeebbb61125b6d17ce14d65c1c4fd9f8bc100c219fc970
6
+ metadata.gz: deebccfd290ebe9bfe5ce6d787a671bd2814ab50da49f139c00eb15231aa431692eaebcceee5611001cfe2a1b2318fb9fa69bd352b470668e3b3435305a989a5
7
+ data.tar.gz: 4ad9301354ec3da5c5adba3eaf80465338f92a6422a4d32e819fbb07158cd2252af4f95ef8c0ec4c1c4ae6813e304242d12488c60ffd966d2633642cc1f7ca0d
checksums.yaml.gz.sig CHANGED
Binary file
data/lib/graphvizml.rb CHANGED
@@ -7,6 +7,7 @@ require 'domle'
7
7
  require 'graphviz'
8
8
  require 'line-tree'
9
9
  require 'tempfile'
10
+ require 'rxfreader'
10
11
 
11
12
 
12
13
  module RegGem
@@ -19,7 +20,7 @@ hkey_gems
19
20
  require graphvizml
20
21
  class GraphVizML
21
22
  media_type svg
22
- '
23
+ '
23
24
  end
24
25
  end
25
26
 
@@ -30,42 +31,42 @@ class GraphVizML
30
31
  attr_reader :g
31
32
 
32
33
  def initialize(obj=nil, debug: false, fill: 'transparent', stroke: '#000', text_color: '#000')
33
-
34
+
34
35
  @debug = debug
35
36
  @fill, @stroke, @text_color = fill, stroke, text_color
36
-
37
+
37
38
  if obj then
38
-
39
-
39
+
40
+
40
41
  xml = if obj.is_a? Rexle or obj.is_a? Rexle::Element
41
-
42
+
42
43
  obj.xml
43
-
44
- else
45
-
44
+
45
+ else
46
+
46
47
  s = RXFHelper.read(obj).first
47
-
48
+
48
49
  if s =~ /<\?graphvizml\b/ then
49
-
50
- import_string s
51
-
50
+
51
+ import_string s
52
+
52
53
  else
53
-
54
+
54
55
  if @debug then
55
56
  #File.write '/tmp/graphviz.xml', xml
56
- puts('graphvizml xml: ' + s.inspect)
57
- end
58
-
57
+ puts('graphvizml xml: ' + s.inspect)
58
+ end
59
+
59
60
  s
60
-
61
+
61
62
  end
62
-
63
+
63
64
  end
64
-
65
+
65
66
  @g = build_from_nodes Domle.new(xml)
66
-
67
+
67
68
  end
68
-
69
+
69
70
  @css = "
70
71
  .node ellipse {stroke: #{stroke}; fill: #{fill}}
71
72
  .node text {fill: #{text_color}}
@@ -74,81 +75,85 @@ class GraphVizML
74
75
  "
75
76
 
76
77
  end
77
-
78
+
78
79
  def import(obj)
79
-
80
- s = RXFHelper.read(obj).first
80
+
81
+ s = RXFReader.read(obj).first
81
82
  xml = import_string s
83
+ puts('graphvizml/import xml: ' + xml.inspect).debug if @debug
82
84
  @g = build_from_nodes Domle.new(xml)
83
85
  self
84
-
86
+
85
87
  end
86
88
 
87
-
89
+
88
90
  def to_dot()
91
+
89
92
  @g.to_dot
93
+
90
94
  end
91
95
 
92
-
96
+
93
97
  # returns an SVG blob
94
98
  #
95
99
  def to_svg()
96
100
  f = Tempfile.new('graphvizml')
97
- Graphviz::output(@g, format: 'svg', path: f.path)
101
+ #jr 26-01-2022 Graphviz::output(@g, format: 'svg', path: f.path)
102
+ Graphviz.output(@g, path: f.path, format: 'svg')
98
103
  s = File.read f.path
99
104
  #s.sub!('xmlns:xlink="http://www.w3.org/1999/xlink"','')
100
105
  #s.sub!('xlink:','') # not yet implemented because of a local namespace issue
101
- s.lines.insert(8, css_code()).join
106
+ s.lines.insert(8, css_code()).join
102
107
  end
103
108
 
104
-
109
+
105
110
  private
106
-
107
-
111
+
112
+
108
113
  def build_from_nodes(doc)
109
114
 
110
115
  puts 'inside build_from_nodes'.info if @debug
111
116
 
112
- g = Graphviz::Graph.new format_summary_attributes(doc.root.attributes)
113
-
114
- # add the nodes
117
+ g = Graphviz::Graph.new **format_summary_attributes(doc.root.attributes)
118
+
119
+ # add the nodes
115
120
 
116
121
  nodes = doc.root.xpath('//node').inject({}) do |r,e|
117
-
122
+
118
123
  r.merge fetch_node(e)
119
124
 
120
125
  end
121
-
126
+
122
127
  if @debug then
123
- puts 'nodes: ' + nodes.inspect
128
+ puts 'nodes: ' + nodes.inspect
124
129
  puts 'doc: ' + doc.root.xml.inspect
125
130
  end
126
131
 
127
132
  a = doc.root.element('style/text()').to_s.strip.split(/}/).map do |entry|
128
-
133
+
129
134
  puts 'entry: ' + entry.inspect if @debug
130
135
 
131
136
  raw_selector,raw_styles = entry.split(/{/,2)
132
137
 
133
- h = raw_styles.strip.split(/;/).inject({}) do |r, x|
138
+ h = raw_styles.strip.split(/;/).inject({}) do |r, x|
134
139
  k, v = x.split(/:/,2).map(&:strip)
135
140
  r.merge(k.to_sym => v)
136
141
  end
137
142
 
138
143
  [raw_selector.split(/,\s*/).map(&:strip), h]
139
144
  end
140
-
145
+
141
146
  puts ' a: ' + a.inspect if @debug
142
-
147
+
143
148
 
144
149
  edge_style = a.any? ? a.find {|x| x[0].grep(/edge/).any?}.last : []
145
150
 
146
-
147
-
148
- # add the edges
151
+
152
+
153
+ # add the edges
149
154
 
150
155
  id_1 = nodes.first[0]
151
- nodes[id_1][-1] = g.add_node(nodes[id_1][0])
156
+ nodes[id_1][-1] = g.add_node(nodes[id_1][0])
152
157
 
153
158
 
154
159
  doc.root.each_recursive do |node|
@@ -156,7 +161,7 @@ class GraphVizML
156
161
  next unless node.name == 'node'
157
162
 
158
163
  node.xpath('a/node | node').each do |child|
159
-
164
+
160
165
  id1, id2 = node.object_id, child.object_id
161
166
 
162
167
  label = child.attributes[:connection].to_s
@@ -167,128 +172,127 @@ class GraphVizML
167
172
 
168
173
  conn = nodes[id1][-1].connections.last
169
174
  conn.attributes[:label] = label
170
-
171
- edge_style.each {|key,val| conn.attributes[key] = m(val) }
172
-
175
+
176
+ edge_style.each {|key,val| conn.attributes[key] = m(val) }
177
+
173
178
  end
174
- end
175
-
176
- format_attributes nodes
177
-
179
+ end
180
+
181
+ format_attributes nodes
182
+
178
183
  g
179
-
184
+
180
185
  end
181
-
186
+
182
187
  def css_code()
183
- <<EOF
188
+ <<EOF
184
189
  <defs>
185
190
  <style type='text/css'><![CDATA[
186
191
  #{@css}
187
192
  ]]></style>
188
- </defs>
189
-
193
+ </defs>
194
+
190
195
  EOF
191
- end
192
-
196
+ end
197
+
193
198
  def fetch_node(node)
194
199
 
195
200
  puts 'inside fetch_node'.info if @debug
196
-
201
+
197
202
  h = node.attributes
198
203
  #puts 'h: ' + h.inspect
199
204
  puts('graphvizml/fetch_node h: ' + h.inspect) if @debug
200
-
205
+
201
206
  if node.parent.name == 'a' then
202
-
207
+
203
208
  url = node.parent.attributes[:href]
204
209
  h[:url] = url if url
205
-
206
- end
210
+
211
+ end
207
212
 
208
213
  id = h[:gid] || node.object_id
209
214
  label = node.text('label')
210
-
215
+
211
216
  # shape options: box, ellipse, record, diamond, circle, polygon, point
212
-
217
+
213
218
  style = {}
214
219
 
215
220
  style[:shape] = h[:shape] if h[:shape] and !h[:shape].empty?
216
221
  style[:URL] = h[:url] if h[:url]
217
222
 
218
223
  #puts "adding node id: %s label: %s" % [id, label]
219
-
220
- # the nil is replaced by the Graphviz node object
224
+
225
+ # the nil is replaced by the Graphviz node object
221
226
  {id => [label, node.style.merge(style), nil]}
222
-
227
+
223
228
  end
224
-
229
+
225
230
  def format_attributes(nodes)
226
-
231
+
227
232
  nodes.each do |id, x|
228
233
 
229
234
  _, attributes, obj = x
230
235
  next unless obj
231
236
  attributes.each {|key, val| obj.attributes[key] = m(val) }
232
-
233
- end
237
+
238
+ end
234
239
 
235
240
  end
236
-
241
+
237
242
  def format_summary_attributes(h)
238
-
239
- type = (h.has_key?(:type) ? h[:type].to_sym : :digraph)
243
+
244
+ type = (h.has_key?(:type) ? h[:type].to_sym : :digraph)
240
245
 
241
246
  h[:type] = type.to_s
242
247
  h[:rankdir] = h.has_key?(:direction) ? h[:direction].to_s.upcase : 'LR'
243
-
244
- %i(recordx_type format_mask schema direction).each do |x|
248
+
249
+ %i(recordx_type format_mask schema direction).each do |x|
245
250
  h.delete x; h.delete x.to_s
246
251
  end
247
-
252
+
248
253
  # remove any entries with an empty value
249
- h.each {|key, value| h.delete key if value.empty?}
250
-
254
+ h.each {|key, value| h.delete key if value.empty?}
255
+
251
256
  h
252
257
  end
253
-
254
-
255
- def import_string(obj)
256
-
257
- s = RXFHelper.read(obj).first
258
-
259
- s2 = s.slice(/<\?graphvizml\b[^>]*\?>/)
258
+
259
+
260
+ def import_string(s)
261
+
262
+
263
+ s2 = s.slice!(/<\?graphvizml\b[^>]*\?>/)
260
264
 
261
265
  if s2 then
262
-
266
+
263
267
  attributes = %w(id fill stroke text_color).inject({}) do |r, keyword|
264
268
  found = s2[/(?<=#{keyword}=['"])[^'"]+/]
265
269
  found ? r.merge(keyword.to_sym => found) : r
266
270
  end
267
-
271
+
268
272
  fill, stroke, text_color = %i(fill stroke text_color).map do |x|
269
273
  attributes[x] ? attributes[x] : method(x).call
270
274
  end
271
-
275
+
272
276
  @css = "
273
277
  .node ellipse {stroke: #{stroke}; fill: #{fill}}
274
278
  .node text {fill: #{text_color}}
275
279
  .edge path {stroke: #{stroke}}
276
280
  .edge polygon {stroke: #{stroke}; fill: #{stroke}}
277
- "
278
-
279
- end
280
-
281
- xml = LineTree.new(s, root: 'nodes', debug: true).to_xml
282
-
281
+ "
282
+
283
+ end
284
+
285
+ xml = LineTree.new(s, root: 'nodes', debug: @debug).to_xml
286
+
283
287
  end
284
-
288
+
285
289
  # modify the value if it matches the following criteria
286
290
  #
287
291
  def m(s)
288
-
292
+
289
293
  # is it a shorthand hexcode? e.g. #fff
290
294
  s.gsub(/^#([\da-f]{3})$/)\
291
295
  { '#' + ($1).chars.inject([]) {|r,x| r << x + x}.join}
292
296
  end
293
-
297
+
294
298
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphvizml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -11,31 +11,31 @@ cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
13
13
  MIIEXjCCAsagAwIBAgIBATANBgkqhkiG9w0BAQsFADAsMSowKAYDVQQDDCFnZW1t
14
- YXN0ZXIvREM9amFtZXNyb2JlcnRzb24vREM9ZXUwHhcNMTkwNjA5MTczOTQxWhcN
15
- MjAwNjA4MTczOTQxWjAsMSowKAYDVQQDDCFnZW1tYXN0ZXIvREM9amFtZXNyb2Jl
16
- cnRzb24vREM9ZXUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDYTr9/
17
- 0s/6N5/dRrEOhJYBRMqcrGr3VC058Pfvii4xqLgy+AHTOxZLEIV5DY5JWICEQGKO
18
- rQUS7iN49f0odEW/7JciVo5yAotUaCVgL/ipjoTt7ti29coGx//9GvGKnEyEAbVu
19
- 3RS7SNDy+zE2MPrGA2d3o2fZ2nl/F8DAQ2zFvmLpa2dQ1mlvO6w/az5Zj/Cqq2Jj
20
- 5x5kVZjNvkt5x7fT0vcZDKuK97ALkiJ/a1iHRxi9fYFBbT3scMvWEzPE55/1mSGJ
21
- tPQF8bt/8krtSQsFqKfEWPaU8CiRT5m3s7CVwMZtAo/Ydo7UyMJ0ZEuviCLvzErS
22
- cyVD6OYF8mQd6gxNnAeHln9SEqDd9A/EOzdm1VYTW5+bicFYApwu34XlJvuqhv/0
23
- NJp6B5qIHnvBzdwjJdx0WuE+p+Rx1AwbwofKxvJogWZ6S9Eh12iV0ZCGob7akga2
24
- 2+tG/ovV3u4VFt4ilJiz4naMmbjkANK8Vag6W/fbhSEJZskle1u9O+aAhOsCAwEA
25
- AaOBijCBhzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU+TngFs1c
26
- eTNQu3YSWDnCD642HKcwJgYDVR0RBB8wHYEbZ2VtbWFzdGVyQGphbWVzcm9iZXJ0
14
+ YXN0ZXIvREM9amFtZXNyb2JlcnRzb24vREM9ZXUwHhcNMjIwMTI2MTk0ODM4WhcN
15
+ MjMwMTI2MTk0ODM4WjAsMSowKAYDVQQDDCFnZW1tYXN0ZXIvREM9amFtZXNyb2Jl
16
+ cnRzb24vREM9ZXUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDXvh01
17
+ vamU8KghEdMGyDHKZFFvDe0WS24O2Z9+aqxDnwBFqhYc7OrPtNltbBcOWSPU8sZ2
18
+ WnMohFCcyEFvbX0krCmHQuKp3EDtgV2jkwRRM4ZTdMPsxbl0ewt4OBGWBgRqpPva
19
+ QQj4nY+70eS2p4Z9NxtKJkjrTaScItrYC8So439THliv6fE/X1wmVthA87QRoLLv
20
+ Nn0ExY9cUkCRhpQ+BKgysDiShBkVeVMD5krTToeF375dhQjYumB6pfRcR3FwZtwA
21
+ 21uslDaVbd2QQ+jvQ7UdvtkAYEtxdQd2sgXlVArLoQq8c7yYZY7OuQtXj71YMJBs
22
+ SyEW5mN3jNpkA34I8K6oxSCtktOpplNVN+qnqEDl0zn1x+ltC99Fw61iwZ0TUuNZ
23
+ iMT7KIkYzaxf2cI9KkPuy8QRBf8h+d1zhNj738isW9DncA8rVlRNbQAnj6zrkUPQ
24
+ 3or24nFsBjLhxG55VtrgG0tYmMdtD4YYZc+AcgjS7PxMLp0xLPMduwq4ftUCAwEA
25
+ AaOBijCBhzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUITb4eCGd
26
+ 35h+35s7ViJVcpR86bYwJgYDVR0RBB8wHYEbZ2VtbWFzdGVyQGphbWVzcm9iZXJ0
27
27
  c29uLmV1MCYGA1UdEgQfMB2BG2dlbW1hc3RlckBqYW1lc3JvYmVydHNvbi5ldTAN
28
- BgkqhkiG9w0BAQsFAAOCAYEAD4OApBYA1uDuqNm0gUyt1Tp1HHyXahpjWMoRx73f
29
- bSGIMkJUBI3JLYuRGb8OGqXhWos4oDhUIGh237BGAmMvQRKXXhMPkzdJSDv8kWKe
30
- aEWXdwAmIT3Kv5YTvOBeT3/e7c11lt2TvfWCz4XiZvvVxIExywsF1WCFQnV64lbT
31
- qa0T9M7swO+0CPatb6qURPG0TNrDma8lw9XzE/PqoNvglLlLIY3SAAMYBq+lPPye
32
- B4b6xjDDOi30/KL/+9fZqo8dDKvlFmRaNDPNJdNcqAYBtbmjM+hmDEeQjaGkwgMV
33
- 8YIyDVvnkB4yrWKOi2zOfslrM65FCFM8AkQzqx0dLknxzxW4lu4Fpqthnt6yHcfQ
34
- IvQKd3YPQuRkcQuotfpJ2QU+ISEi1sw2Zcn7RARz+17XPkQZPnxknSLEJQtA+UT3
35
- /8tqxCi/5ePYzYvc/FsI9Y1IJRY3sAZ8QYkhQ1+eHM4Q6WnPySjokqiHaKUI3rHR
36
- 7J+rmK2Wu7bYff3C/pg+xkkg
28
+ BgkqhkiG9w0BAQsFAAOCAYEACtwXE0bRRrEC5NqayvsRvVTLJYs1mHMWBfsPXBFZ
29
+ auEcRhToEKNQfW1eQxYMyaMiLVphzoPTAKgM36SrCd6fbSS40djlX8tXlr9N7EIC
30
+ 8cV4BiDWNTyNItJgsZpDSXvWmorO0sxFdS3bX+wGpIqjTucov3xCL29oipOTed78
31
+ CiGPYDYX2ddYBPv4DCnKRlmpbQPSEAv+Vr4MIXK2DIz/pNKhVkO60CkhQLfbmuIt
32
+ tHEHxLaJBrdFImPRVRDbCA7h+a5QyotAldi99hPBCdxS5CyAaFQkn5ScfyBbGOla
33
+ 88GxnM8dyYQwA7jGKJzEVP4Oe2tIlC66Cuvt9aFJY5ILYAvn8yaL9Zz/jfvK/txT
34
+ g5jRbEphIM24ZKx4Ujg457ks1jQG6qQxzJOQk1dDKsKzY+75/npWJbZFPCdpEX1l
35
+ n5la83UsDTB94LHIHb/W8YdApT3vWP/4nxl+/aAPJPBgyN8mZ4Td0FFgbaPGbW4e
36
+ PxZXxv6QqQ7uOHhRsvNRkYj3
37
37
  -----END CERTIFICATE-----
38
- date: 2019-06-09 00:00:00.000000000 Z
38
+ date: 2022-02-23 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: domle
@@ -43,62 +43,62 @@ dependencies:
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '0.3'
46
+ version: '0.6'
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 0.3.1
49
+ version: 0.6.0
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - "~>"
55
55
  - !ruby/object:Gem::Version
56
- version: '0.3'
56
+ version: '0.6'
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 0.3.1
59
+ version: 0.6.0
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: graphviz
62
62
  requirement: !ruby/object:Gem::Requirement
63
63
  requirements:
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- version: 1.1.0
67
64
  - - "~>"
68
65
  - !ruby/object:Gem::Version
69
- version: '1.1'
66
+ version: '1.2'
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 1.2.1
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: 1.1.0
77
74
  - - "~>"
78
75
  - !ruby/object:Gem::Version
79
- version: '1.1'
76
+ version: '1.2'
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 1.2.1
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: line-tree
82
82
  requirement: !ruby/object:Gem::Requirement
83
83
  requirements:
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- version: 0.8.0
87
84
  - - "~>"
88
85
  - !ruby/object:Gem::Version
89
- version: '0.8'
86
+ version: '0.9'
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 0.9.3
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: 0.8.0
97
94
  - - "~>"
98
95
  - !ruby/object:Gem::Version
99
- version: '0.8'
96
+ version: '0.9'
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 0.9.3
100
100
  description:
101
- email: james@jamesrobertson.eu
101
+ email: digital.robertson@gmail.com
102
102
  executables: []
103
103
  extensions: []
104
104
  extra_rdoc_files: []
@@ -116,14 +116,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ">="
118
118
  - !ruby/object:Gem::Version
119
- version: '0'
119
+ version: 3.0.2
120
120
  required_rubygems_version: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  requirements: []
126
- rubygems_version: 3.0.1
126
+ rubygems_version: 3.2.22
127
127
  signing_key:
128
128
  specification_version: 4
129
129
  summary: Generates an SVG file from GraphViz using a GraphViz Markup Language file
metadata.gz.sig CHANGED
Binary file