omf_web 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -20,6 +20,7 @@ Gemfile.lock
20
20
  share/htdocs/vendor/valums-file-uploader-cf7bfb1/.gitignore
21
21
  share/htdocs/vendor/valums-file-uploader-cf7bfb1/.gitignore
22
22
  .project
23
+ .settings
23
24
 
24
25
  UNUSED/
25
26
  *.swp
@@ -27,3 +28,4 @@ UNUSED/
27
28
 
28
29
  share/htdocs/vendor/jquery-ui-1.8.23/development-bundle
29
30
  example/wimax
31
+ vendor
@@ -0,0 +1,12 @@
1
+ server:
2
+ page_title: 'Tutorial 1'
3
+ port: 4030
4
+
5
+ tabs:
6
+ - name: Main
7
+ priority: 300
8
+ widgets:
9
+ - name: Description
10
+ type: text
11
+ content:
12
+ text: Hello World!
@@ -0,0 +1 @@
1
+ ts:double,generator:string,voltage:double,noise:double
@@ -0,0 +1,28 @@
1
+ server:
2
+ page_title: 'Tutorial 2'
3
+ port: 4030
4
+
5
+ data_sources:
6
+ - id: voltage
7
+ file: gen.csv
8
+
9
+ tabs:
10
+ - name: Main
11
+ priority: 300
12
+ widgets:
13
+ - name: Generator
14
+ type: data/line_chart3
15
+ data_source:
16
+ name: voltage
17
+ mapping:
18
+ x_axis: ts
19
+ y_axis: voltage
20
+ group_by: generator
21
+ axis:
22
+ x:
23
+ legend: Time [sec]
24
+ y:
25
+ legend: Voltage [V]
26
+ ticks:
27
+ format: ".2s"
28
+
@@ -0,0 +1,37 @@
1
+ server:
2
+ page_title: Tutorial 3 - Stacked Widgets
3
+ port: 4030
4
+
5
+ data_sources:
6
+ - id: voltage
7
+ file: ../tut02/gen.csv
8
+
9
+ tabs:
10
+ - name: Main
11
+ priority: 300
12
+ widgets:
13
+ - type: layout/stacked
14
+ info: This widget shows the voltage reported for varous generators
15
+ widgets:
16
+ - name: Generator
17
+ type: data/line_chart3
18
+ data_source:
19
+ name: voltage
20
+ mapping:
21
+ x_axis: ts
22
+ y_axis: voltage
23
+ group_by: generator
24
+ axis:
25
+ x:
26
+ legend: Time [sec]
27
+ y:
28
+ legend: Voltage [V]
29
+ ticks:
30
+ format: ".2s"
31
+
32
+ - name: Table
33
+ type: data/table2
34
+ data_source:
35
+ name: voltage
36
+
37
+
@@ -0,0 +1,56 @@
1
+ require 'sequel'
2
+
3
+ File.unlink('gen.sq3') if File.readable?('gen.sq3')
4
+ db = Sequel.connect 'sqlite://gen.sq3'
5
+
6
+ db.create_table '_senders'.to_sym do
7
+ Integer :id
8
+ String :name
9
+ end
10
+ db['_senders'.to_sym].insert(id: 1, name: 'test')
11
+
12
+ db.create_table :voltage do
13
+ Integer :oml_sender_id
14
+ Integer :oml_seq
15
+ Float :oml_ts_client
16
+ Float :oml_ts_server
17
+ String :generator
18
+ Float :voltage
19
+ Float :noise
20
+ end
21
+ $out_t = db[:voltage]
22
+ $seq = 0
23
+
24
+
25
+ $start = Time.now.to_i
26
+ def measure(gen, voltage, noise)
27
+ now = Time.now.to_f - $start
28
+ r = {
29
+ oml_sender_id: 1, oml_seq: $seq,
30
+ oml_ts_client: now, oml_ts_server: now,
31
+ generator: gen,
32
+ voltage: voltage,
33
+ noise: noise
34
+ }
35
+ $out_t.insert(r)
36
+ $seq += 1
37
+ end
38
+
39
+ def r; rand - 0.5; end
40
+ def noise(mul); return 4 * mul * r() * r(); end
41
+
42
+ ang = 0;
43
+ step = Math::PI * 15 / 180;
44
+ loop do
45
+ n1 = noise(0.02);
46
+ a1 = Math.sin(ang);
47
+ measure('gen1', a1 + n1, n1);
48
+ n2 = noise(0.01);
49
+ a2 = Math.cos(ang);
50
+ measure('gen2', a2 + n2, n2);
51
+ ang += step;
52
+
53
+ sleep 0.2
54
+ end
55
+
56
+
Binary file
@@ -0,0 +1,47 @@
1
+ server:
2
+ page_title: Tutorial 4 - Realtime Graph
3
+ port: 4030
4
+
5
+ data_sources:
6
+ - id: voltage
7
+ table: voltage
8
+ check_interval: 2
9
+ max_size: 100
10
+ database:
11
+ id: gen
12
+ url: sqlite:gen.sq3
13
+
14
+ tabs:
15
+ - name: Main
16
+ priority: 300
17
+ widgets:
18
+ - name: Voltage
19
+ type: data/line_chart3
20
+ data_source:
21
+ name: voltage
22
+ mapping:
23
+ x_axis: oml_ts_client
24
+ y_axis: voltage
25
+ group_by: generator
26
+ axis:
27
+ x:
28
+ legend: Time [sec]
29
+ y:
30
+ legend: Voltage [V]
31
+
32
+ - name: Noise
33
+ type: data/line_chart3
34
+ data_source:
35
+ name: voltage
36
+ mapping:
37
+ x_axis: oml_ts_client
38
+ y_axis: noise
39
+ group_by: generator
40
+ axis:
41
+ x:
42
+ legend: Time [sec]
43
+ y:
44
+ legend: Noise [V]
45
+ ticks:
46
+ format: ".2s"
47
+
@@ -0,0 +1,125 @@
1
+ protocol: 4
2
+ content: text
3
+ domain: foo
4
+ start-time: 1387441246
5
+ sender-id: maxs-laptop-3.local-35511
6
+ app-name: gen
7
+ schema: 0 _experiment_metadata subject:string key:string value:string
8
+ schema: 1 gen_voltage generator:string voltage:double noise:double
9
+
10
+ 0.000541 1 1 gen1 0.009052262991847197 0.009052262991847197
11
+ 0.000664 1 2 gen2 1.000238176848893 0.00023817684889296177
12
+ 0.201854 1 3 gen1 0.258828739904194 9.69480167331446e-06
13
+ 0.202005 1 4 gen2 0.9688224880955606 0.0028966618064922662
14
+ 0.403129 1 5 gen1 0.49822187353019903 -0.001778126469800914
15
+ 0.403243 1 6 gen2 0.8685805711612515 0.0025551673768128393
16
+ 0.604439 1 7 gen1 0.7018571673754107 -0.005249613811136794
17
+ 0.604592 1 8 gen2 0.6990906726275941 -0.008016108558953511
18
+ 0.805799 1 9 gen1 0.8686216754782153 0.002596271693776792
19
+ 0.805913 1 10 gen2 0.5067729259799549 0.006772925979954824
20
+ 1.006974 1 11 gen1 0.9766814852388673 0.01075565894979911
21
+ 1.007052 1 12 gen2 0.2554201612589873 -0.0033988838435336293
22
+ 1.208202 1 13 gen1 0.9881295616745925 -0.011870438325407514
23
+ 1.208353 1 14 gen2 0.004175973494518424 0.00417597349451814
24
+ 1.409569 1 15 gen1 0.9636146565567362 -0.0023111697323322067
25
+ 1.409766 1 16 gen2 -0.2583664043495907 0.000452640752929745
26
+ 1.611001 1 17 gen1 0.8699910119123253 0.003965608127886516
27
+ 1.611267 1 18 gen2 -0.4963357508476029 0.0036642491523969038
28
+ 1.812464 1 19 gen1 0.707125179793902 1.8398607354376904e-05
29
+ 1.812626 1 20 gen2 -0.7117504151926574 -0.004643634006109943
30
+ 2.013795 1 21 gen1 0.49782332897361886 -0.002176671026381096
31
+ 2.013949 1 22 gen2 -0.8671805905869713 -0.0011551868025326008
32
+ 2.214493 1 23 gen1 0.2759681841041199 0.017149139001599305
33
+ 2.214763 1 24 gen2 -0.9659284181391053 -2.591850037057478e-06
34
+ 2.415727 1 25 gen1 0.006502606057286958 0.00650260605728728
35
+ 2.41585 1 26 gen2 -0.9989695805772422 0.0010304194227578425
36
+ 2.616185 1 27 gen1 -0.2474792019788636 0.011339843123657626
37
+ 2.616457 1 28 gen2 -0.9665593639002044 -0.0006335376111361135
38
+ 2.817713 1 29 gen1 -0.500986141433576 -0.000986141433575397
39
+ 2.817904 1 30 gen2 -0.8640558969794142 0.0019695068050241704
40
+ 3.018555 1 31 gen1 -0.709341248186044 -0.002234466999496018
41
+ 3.018822 1 32 gen2 -0.703823503254065 0.0032832779324820107
42
+ 3.220049 1 33 gen1 -0.8540833586659958 0.011942045118443004
43
+ 3.220201 1 34 gen2 -0.491698229883797 0.008301770116202652
44
+ 3.421419 1 35 gen1 -0.978054979433912 -0.01212915314484368
45
+ 3.421512 1 36 gen2 -0.26191057760657466 -0.003091532504054028
46
+ 3.622692 1 37 gen1 -1.0041761696946705 -0.004176169694670427
47
+ 3.622888 1 38 gen2 0.000266109456927552 0.0002661094569277357
48
+ 3.824131 1 39 gen1 -0.9660244364327265 -9.861014365809152e-05
49
+ 3.82423 1 40 gen2 0.2655018642868284 0.006682819184308119
50
+ 4.024601 1 41 gen1 -0.8672992538615825 -0.001273850077143368
51
+ 4.024755 1 42 gen2 0.4965828131825105 -0.0034171868174887833
52
+ 4.225872 1 43 gen1 -0.7145364332624615 -0.007429652075913183
53
+ 4.226061 1 44 gen2 0.7094198260620043 0.0023130448754576072
54
+ 4.427303 1 45 gen1 -0.49553047196513217 0.004469528034869077
55
+ 4.427431 1 46 gen2 0.8664569342400065 0.0004315304555685775
56
+ 4.628538 1 47 gen1 -0.25868741744082724 0.0001316276616951693
57
+ 4.628651 1 48 gen2 0.9695495593984652 0.0036237331093973346
58
+ 4.829546 1 49 gen1 -0.0056269230441516015 -0.0056269230441495805
59
+ 4.829678 1 50 gen2 1.000286677159241 0.0002866771592408587
60
+ 5.030135 1 51 gen1 0.26221854668419375 0.0033995015816752445
61
+ 5.030333 1 52 gen2 0.9633585409841711 -0.0025672853048978326
62
+ 5.231567 1 53 gen1 0.49777042942797545 -0.0022295705720222583
63
+ 5.231723 1 54 gen2 0.8667578290164825 0.0007324252320425557
64
+ 5.432044 1 55 gen1 0.7099132050047163 0.002806423818170901
65
+ 5.432202 1 56 gen2 0.709795708621591 0.0026889274350414567
66
+ 5.633394 1 57 gen1 0.8765279299793987 0.010502526194961571
67
+ 5.633502 1 58 gen2 0.5024812578225554 0.0024812578225524903
68
+ 5.834711 1 59 gen1 0.9576089552031831 -0.008316871085884175
69
+ 5.834844 1 60 gen2 0.2632904070984241 0.004471361995899884
70
+ 6.035931 1 61 gen1 1.0036072780529801 0.0036072780529801925
71
+ 6.036029 1 62 gen2 -0.002945853864879225 -0.002945853864883084
72
+ 6.236382 1 63 gen1 0.9793047816231178 0.013378955334048552
73
+ 6.236551 1 64 gen2 -0.2535797763911805 0.005239268711336159
74
+ 6.437722 1 65 gen1 0.867501846509946 0.001476442725505107
75
+ 6.437851 1 66 gen2 -0.5016559171277346 -0.00165591712773846
76
+ 6.639042 1 67 gen1 0.7105133062669828 0.003406525080431909
77
+ 6.639149 1 68 gen2 -0.7118657833841097 -0.004759002197565484
78
+ 6.840287 1 69 gen1 0.5010374979712995 0.0010374979712951564
79
+ 6.840395 1 70 gen2 -0.8631536228642781 0.0028717809201580504
80
+ 7.041641 1 71 gen1 0.26104366950719377 0.0022246244046677344
81
+ 7.041746 1 72 gen2 -0.9673391716909063 -0.0014133454018395162
82
+ 7.242609 1 73 gen1 0.013138412276303276 0.013138412276297579
83
+ 7.242768 1 74 gen2 -0.996419808970396 0.0035801910296040015
84
+ 7.443049 1 75 gen1 -0.2594940717844798 -0.0006750266819648325
85
+ 7.443209 1 76 gen2 -0.9655017940568454 0.0004240322322244331
86
+ 7.643754 1 77 gen1 -0.5017280961989892 -0.0017280961989946213
87
+ 7.643855 1 78 gen2 -0.8666439757350138 -0.0006185719505720662
88
+ 7.845024 1 79 gen1 -0.710833044153964 -0.0037262629674211134
89
+ 7.845185 1 80 gen2 -0.712118404232411 -0.005011623045858907
90
+ 8.04634 1 81 gen1 -0.8639890749334213 0.0020363288510139134
91
+ 8.046444 1 82 gen2 -0.4981155461038007 0.0018844538962052737
92
+ 8.247403 1 83 gen1 -0.9724175093298063 -0.006491683040739884
93
+ 8.247521 1 84 gen2 -0.2629917637412665 -0.004172718638738747
94
+ 8.448396 1 85 gen1 -0.9972626574173751 0.002737342582624884
95
+ 8.448503 1 86 gen2 -0.006205879343863204 -0.00620587934385567
96
+ 8.649184 1 87 gen1 -0.969092076529548 -0.003166250240477721
97
+ 8.649359 1 88 gen2 0.26237290188814333 0.003553856785630157
98
+ 8.850467 1 89 gen1 -0.8678365955717785 -0.0018111917873358183
99
+ 8.850546 1 90 gen2 0.49936766720269943 -0.0006323327972934984
100
+ 9.05164 1 91 gen1 -0.6947241904470202 0.012382590739533293
101
+ 9.051749 1 92 gen2 0.7043420965663202 -0.0027646846202214366
102
+ 9.252116 1 93 gen1 -0.5000611405373083 -6.114053730073697e-05
103
+ 9.252231 1 94 gen2 0.8650205513420002 -0.0010048524424341925
104
+ 9.452679 1 95 gen1 -0.2611463705367044 -0.0023273254341748947
105
+ 9.452769 1 96 gen2 0.9714777673088831 0.005551941019817127
106
+ 9.653985 1 97 gen1 0.0009345045086265564 0.000934504508635928
107
+ 9.654093 1 98 gen2 1.0019024678600363 0.001902467860036351
108
+ 9.854806 1 99 gen1 0.2595686111414282 0.0007495660389167818
109
+ 9.854918 1 100 gen2 0.9658598738139401 -6.595247513067116e-05
110
+ 10.056092 1 101 gen1 0.4957794151569727 -0.004220584843018661
111
+ 10.056316 1 102 gen2 0.8639320769128302 -0.002093326871613348
112
+ 10.2573 1 103 gen1 0.7099559913341272 0.0028492101475869757
113
+ 10.257393 1 104 gen2 0.7007690522692515 -0.006337728917303325
114
+ 10.45836 1 105 gen1 0.8665676027571488 0.0005421989727154917
115
+ 10.458579 1 106 gen2 0.5003270197892833 0.00032701978927404625
116
+ 10.659818 1 107 gen1 0.9615923308294252 -0.004333495459640287
117
+ 10.659953 1 108 gen2 0.2579735203771516 -0.0008455247253796604
118
+ 10.860999 1 109 gen1 1.0000405508627024 4.05508627023924e-05
119
+ 10.861083 1 110 gen2 -0.000981461777728295 -0.0009814617777395042
120
+ 11.062217 1 111 gen1 0.9579223304488469 -0.008003495840224447
121
+ 11.062359 1 112 gen2 -0.25996047914817483 -0.0011414340456651958
122
+ 11.263536 1 113 gen1 0.8648213953446445 -0.0012040084398000131
123
+ 11.263635 1 114 gen2 -0.4991642283075432 0.0008357716924465582
124
+ 11.464841 1 115 gen1 0.7030706949442987 -0.004036086242257328
125
+ 11.464939 1 116 gen2 -0.7052689708758774 0.0018378103106615525
@@ -0,0 +1,36 @@
1
+ require 'oml4r'
2
+
3
+
4
+ class GenMP < OML4R::MPBase
5
+ name :voltage
6
+
7
+ param :generator
8
+ param :voltage, :type => :double
9
+ param :noise, :type => :double
10
+ end
11
+
12
+ opts = {
13
+ :appName => 'gen',
14
+ :domain => 'foo',
15
+ :collect => 'tcp:localhost:4003'
16
+ }
17
+ OML4R::init(ARGV, opts)
18
+
19
+ def r; rand - 0.5; end
20
+ def noise(mul); return 4 * mul * r() * r(); end
21
+
22
+ ang = 0;
23
+ step = Math::PI * 15 / 180;
24
+ loop do
25
+ n1 = noise(0.02);
26
+ a1 = Math.sin(ang);
27
+ GenMP.inject('gen1', a1 + n1, n1);
28
+ n2 = noise(0.01);
29
+ a2 = Math.cos(ang);
30
+ GenMP.inject('gen2', a2 + n2, n2);
31
+ ang += step;
32
+
33
+ sleep 0.2
34
+ end
35
+
36
+
@@ -0,0 +1,47 @@
1
+ server:
2
+ page_title: Tutorial 5 - OML Direct Graphs
3
+ port: 4030
4
+
5
+ data_sources:
6
+ - id: voltage
7
+ max_size: 100
8
+ omsp:
9
+ port: 4003
10
+ stream_name: gen_voltage
11
+
12
+ tabs:
13
+ - name: Main
14
+ priority: 300
15
+ widgets:
16
+ - name: Voltage
17
+ type: data/line_chart3
18
+ data_source:
19
+ name: voltage
20
+ mapping:
21
+ x_axis: oml_ts
22
+ y_axis: voltage
23
+ group_by: generator
24
+ axis:
25
+ x:
26
+ legend: Time [sec]
27
+ y:
28
+ legend: Voltage [V]
29
+
30
+ - name: Noise
31
+ type: data/histogram2
32
+ info: This widget shows the distribution of the noise on the generator output.
33
+ density: true
34
+ data_source:
35
+ name: voltage
36
+ mapping:
37
+ value: noise
38
+ group_by: generator
39
+ axis:
40
+ x:
41
+ legend: Noise (V)
42
+ ticks:
43
+ format: ".2s"
44
+ y:
45
+ legend: Density
46
+
47
+
@@ -135,9 +135,9 @@ module OMF::Web
135
135
  res = []
136
136
  fs = _find_files(search_pattern, tree, nil, res)
137
137
 
138
- if (mt = opts[:mime_type])
139
- fs = fs.select { |f| f[:mime_type] == mt }
140
- end
138
+ # if (mt = opts[:mime_type])
139
+ # fs = fs.select { |f| File.fnmatch(mt, f[:mime_type]) }
140
+ # end
141
141
  fs
142
142
  end
143
143
 
@@ -116,7 +116,8 @@ module OMF::Web
116
116
  path = e.path
117
117
  if path.match(search_pattern)
118
118
  mt = mime_type_for_file(path)
119
- next if mime_type != nil && mime_type != mt
119
+ # subselect mime type in class method
120
+ #next if mime_type != nil && !File.fnmatch(mime_type, mt)
120
121
  res << {:url => get_url_for_path(path), :path => path, #:name => 'foo',
121
122
  :mime_type => mt}
122
123
  end
@@ -128,7 +128,12 @@ module OMF::Web
128
128
  fsa = (opts[:repo_iterator] || [@@primary_repository]).map do |repo|
129
129
  repo.find_files(selector, opts)
130
130
  end
131
+
131
132
  fs = fsa.flatten
133
+ if (mt = opts[:mime_type])
134
+ fs = fs.select { |f| File.fnmatch(mt, f[:mime_type]) }
135
+ end
136
+
132
137
  if (max = opts[:max])
133
138
  fs = fs[0, max]
134
139
  end
@@ -18,7 +18,7 @@ module OMF::Web
18
18
  # @returns url for repo
19
19
  #
20
20
  def self.create_from_text(descr, opts)
21
- puts "STATIC>>> #{opts}"
21
+ #puts "STATIC>>> #{opts}"
22
22
  unless (text = descr[:text])
23
23
  text "Missing 'text' declaration in 'content'"
24
24
  end
@@ -46,12 +46,18 @@ module OMF::Web
46
46
  end
47
47
 
48
48
  def self.[](name)
49
+ find(name)
50
+ end
51
+
52
+ def self.find(name, warn_if_not_exist = true)
49
53
  name = name.to_sym
50
54
  unless dsp = OMF::Web::SessionStore[name, :dsp]
51
55
  if ds = @@datasources[name]
52
56
  dsp = OMF::Web::SessionStore[name, :dsp] = self.new(name, ds)
53
57
  else
54
- warn "Requesting unknown datasource '#{name}', only know about '#{@@datasources.keys.join(', ')}'."
58
+ if warn_if_not_exist
59
+ warn "Requesting unknown datasource '#{name}', only know about '#{@@datasources.keys.join(', ')}'."
60
+ end
55
61
  end
56
62
  end
57
63
  dsp
@@ -109,7 +115,7 @@ module OMF::Web
109
115
  return [proxy]
110
116
  end
111
117
 
112
- attr_reader :name
118
+ attr_reader :name, :data_source
113
119
 
114
120
  def reset()
115
121
  # TODO: Figure out partial sending
@@ -147,26 +153,28 @@ module OMF::Web
147
153
  dsp
148
154
  end
149
155
 
150
- def to_javascript(opts = {})
151
- #puts "to_java>>>>> #{opts.inspect}"
156
+ def to_hash(opts = {})
152
157
  sid = Thread.current["sessionID"]
153
158
  opts = opts.dup
154
- opts[:name] = @name
159
+ opts[:name] ||= @name
160
+ opts[:id] = @name
161
+ opts[:stream] = @name # TODO: Should retire. Code should use :id
155
162
  opts[:schema] = @data_source.schema.describe
156
- opts[:update_url] = "/_update/#{@name}?sid=#{sid}"
163
+ opts[:update_url] ||= "/_update/#{@name}?sid=#{sid}"
164
+ opts[:ws_url] ||= "/_ws?sid=#{sid}"
157
165
  opts[:sid] = sid
158
- #opts[:is_static] = (@data_source.respond_to? :static?) ? @data_source.static? : false
159
166
  unless opts[:slice] # don't send any data if this is a sliced one
160
- #opts[:rows] = @data_source.rows[0 .. 20]
161
167
  opts[:rows] = []
162
168
  opts[:offset] = @data_source.offset
163
169
  end
164
- #puts "to_java2>>>>> #{opts.inspect}"
170
+ opts
171
+ end
165
172
 
173
+ def to_javascript(opts = {})
174
+ opts = to_hash(opts)
166
175
  %{
167
176
  ds.register(#{opts.to_json});
168
177
  }
169
-
170
178
  end
171
179
 
172
180
  def initialize(name, data_source)
@@ -48,8 +48,26 @@ module OMF::Web
48
48
  def self.find_across_sessions(&block)
49
49
  @@sessions.values.map { |v| v[:content] }.find(&block)
50
50
  end
51
+
52
+ # Return a session context which will execute block given to
53
+ # #call in this session context
54
+ #
55
+ def self.session_context
56
+ SessionContext.new
57
+ end
51
58
  end # SessionStore
52
59
 
60
+ class SessionContext
61
+ def initialize
62
+ @sid = Thread.current["sessionID"]
63
+ end
64
+
65
+ def call(&block)
66
+ Thread.current["sessionID"] = @sid
67
+ block.call
68
+ end
69
+ end
70
+
53
71
  end # OMF:Web
54
72
 
55
73
 
@@ -46,7 +46,7 @@ module OMF::Web::Theme
46
46
  div :id => base_id, :class => "codemirror_widget" do
47
47
 
48
48
  js_toolbar = []
49
- div :class => "codemirror_toolbar_container widget-toolbar" do
49
+ div :class => "codemirror_toolbar_container widget_toolbar" do
50
50
  ol :class => "codemirror_toolbar" do
51
51
  ['save', 'undo', 'redo'].each do |name|
52
52
  id = "#{base_id}_#{name}_a"