squared 0.0.7 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45b563863fb21461ec7c629dc01a197485c15c8a26239db170a91970a6cade9a
4
- data.tar.gz: f7051ae9101dbced194185f5731c6bd028ccd3e56dfbbab047a7370c220412de
3
+ metadata.gz: d9b753ae5817f7ddd43ccf1152dde2bd4bc8d37ed2eae1d39d7c118e84c20947
4
+ data.tar.gz: 910b375d08c1fda296862a22e612832eb0ebbbea505a6d860f2db9e48ff9a2ee
5
5
  SHA512:
6
- metadata.gz: 74adde082a170b07b65ccc258b94681826c9fdbda9120a39128f9236d4215c904a7dac32451428e92cdfbabd354e6dce810447df03660169b34783d02a808978
7
- data.tar.gz: c50ee1d27e5be607e84fd82bd4d15e4d3ec8e4d12acd4619ef1421d2206e313205e8aaf849965e6140d6e5873848001d2c55d00f0335f8274ef6c95213ec7990
6
+ metadata.gz: 3595a660add974bb7bf69df55aaca30d7fb8bfb47ae21cdfd0b5d978ce36f35acb97e15f746d97204afa1a800c639a028e3835a9431addf63e6eb6402df6f87c
7
+ data.tar.gz: cda2b5a2aa217354d8f06d307c3136ae25d77358b0a478195c7ad945701f08f1e16450340819bd1a41e958a1a31f5e4b13ce167dee4a0d40630f4a3e9a61ada7
data/README.ruby.md CHANGED
@@ -36,10 +36,11 @@ require "squared/workspace/repo" # Repo (optional)
36
36
 
37
37
  # REPO_ROOT = /workspaces
38
38
  # REPO_HOME = /workspaces/squared
39
+ # NODE_ENV = production
39
40
  # rake = /workspaces/squared/Rakefile
40
41
 
41
42
  Workspace::Application
42
- .new("squared") # REPO_HOME
43
+ .new(main: "squared") # Dir.pwd? (main? is implicitly basename)
43
44
  .repo("https://github.com/anpham6/squared-repo", "nightly", run: "build", ref: :node) # Repo (optional)
44
45
  .run("rake install", ref: :ruby)
45
46
  .depend(false, group: "default")
@@ -48,11 +49,11 @@ Workspace::Application
48
49
  .add("pathname", run: "rake compile", copy: "rake install", test: "rake test", group: "default", ref: :ruby) # Ruby (with C extensions)
49
50
  .add("optparse", doc: "rake rdoc", group: "default") # Uses bundler/gem_tasks (without C extensions)
50
51
  .add("logger", copy: { from: "lib", glob: "**/*.rb", gemdir: "~/.rvm/gems/ruby-3.3.5/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
51
- .add("android", "android-docs", run: false, doc: "make html", ref: :python) # Python
52
52
  .add("emc", "e-mc", copy: { from: "publish", into: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node) # Node
53
53
  .add("pir", "pi-r", copy: { from: "publish", into: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
54
54
  .add("squared", log: { file: "tmp/%Y-%m-%d.log", level: "debug" }, group: "app") # Copy target (main)
55
- .style(:banner, 255.255) # 256 colors (fg | fg.bg | -0.bg)
55
+ .add("sqd", "squared/sqd", script: ["build:sqd", "prod:sqd"], depend: false, clean: ["build/sqd/"], exclude: :git) # NPM workspaces
56
+ .style("banner", 255.255) # 256 colors (fg | fg.bg | -0.bg)
56
57
  .build(default: "status", parallel: ["pull", "fetch", "rebase", "copy", "clean"]) do |workspace|
57
58
  workspace
58
59
  .enable_aixterm
@@ -64,21 +65,32 @@ Workspace::Application
64
65
  # pathname = /workspaces/pathname
65
66
  # optparse = /workspaces/optparse
66
67
  # log = /workspaces/logger
67
- # android = /workspaces/android-docs
68
68
  # emc = /workspaces/e-mc
69
69
  # pir = /workspaces/pi-r
70
70
  # squared = /workspaces/squared
71
71
 
72
72
  Workspace::Application
73
- .new("squared")
74
- .group("default", "ruby", run: "rake build", copy: "rake install", clean: "rake clean", override: {
75
- pathname: { run: "rake compile" }
73
+ .new(ENV["SQUARED_DIR"], prefix: "rb", common: false) # Has empty styles
74
+ .group("default", "ruby", run: "rake build", copy: "rake install", clean: "rake clean", ref: :ruby, override: {
75
+ pathname: {
76
+ run: "rake compile" # rake rb:pathname:build
77
+ }
76
78
  })
79
+ .with(ref: :python) do # Python
80
+ doc("make html") # rake rb:doc | rb:doc:python
81
+ run(false) # rake rb:build (disabled)
82
+ exclude(%i[base git]) # superclass
83
+ add("android", "android-docs") # rake rb:android:doc
84
+ add("chrome", "chrome-docs") # rake rb:chrome:doc
85
+ end
86
+ .style("inline", "bold")
77
87
  .build
78
88
  # default = /workspaces/ruby/*
79
89
  # pathname = /workspaces/ruby/pathname
80
90
  # optparse = /workspaces/ruby/optparse
81
91
  # logger = /workspaces/ruby/logger
92
+ # android = /workspaces/android-docs
93
+ # chrome = /workspaces/chrome-docs
82
94
  ```
83
95
 
84
96
  **NOTE**: The use of "**ref**" (class name) is only necessary when running `repo:init` for the first time into an empty directory.
@@ -124,6 +136,7 @@ rake clean:node # none + ["publish/**/*.js", "tmp/"] + ["build/"]
124
136
  * header
125
137
  * active
126
138
  * inline
139
+ * major
127
140
 
128
141
  ## LICENSE
129
142
 
@@ -26,7 +26,8 @@ module Squared
26
26
  workspace: {
27
27
  header: %i[bold],
28
28
  active: %i[bold],
29
- inline: %i[bold]
29
+ inline: %i[bold],
30
+ major: %i[bold]
30
31
  },
31
32
  project: {},
32
33
  viewer: {
@@ -82,16 +83,15 @@ module Squared
82
83
  args.reject(&:empty?).join(' => ') + (hint ? " (#{hint})" : '')
83
84
  end
84
85
 
85
- def as_a(obj, flat: nil)
86
- if obj.nil?
87
- []
88
- elsif !obj.is_a?(::Array)
89
- [obj]
86
+ def as_a(obj, meth = nil, flat: nil)
87
+ return [] if obj.nil?
88
+
89
+ if !obj.is_a?(::Array)
90
+ obj = [obj]
90
91
  elsif flat
91
- obj.flatten(flat == true ? nil : flat)
92
- else
93
- obj
92
+ obj = obj.flatten(flat == true ? nil : flat)
94
93
  end
94
+ meth ? obj.map(&meth) : obj
95
95
  end
96
96
  end
97
97
  end
@@ -201,7 +201,7 @@ module Squared
201
201
  "| #{s} |"
202
202
  end
203
203
  out << bord
204
- out.push(pr.(title), bord) if title
204
+ out << pr.(title) << bord if title
205
205
  lines.each { |line| out << pr.(line) }
206
206
  out << bord
207
207
  if block_given?
@@ -7,12 +7,12 @@ module Squared
7
7
  module Task
8
8
  module_function
9
9
 
10
- def invoke(name, *args, exception: true)
10
+ def invoke(name, *args, exception: true, warning: true)
11
11
  ::Rake::Task[name].invoke(*args)
12
12
  rescue StandardError => e
13
13
  raise if exception
14
14
 
15
- warn e
15
+ warn e if warning
16
16
  end
17
17
 
18
18
  def invoked?(name)
@@ -17,14 +17,15 @@ module Squared
17
17
  end
18
18
  end
19
19
 
20
- attr_reader :name, :main, :project, :theme
20
+ attr_reader :main, :name, :project, :theme
21
21
 
22
- def initialize(main, name = nil, project: nil, dump: nil, opts: {}, auto: true, common: true)
22
+ def initialize(main, name = nil, project: nil, prefix: nil, dump: nil, opts: {}, auto: true, common: true)
23
23
  if project
24
24
  main = @project.base_path(main).to_s if (@project = __get__(:project)[project.to_sym])
25
25
  @required = true
26
26
  end
27
27
  @name = name&.to_s || @project&.name
28
+ @prefix = prefix
28
29
  @ext = File.extname(main)
29
30
  @dump = dump
30
31
  @mime = {}
@@ -59,18 +60,19 @@ module Squared
59
60
 
60
61
  params = ->(args) { exist? ? [realpath, [args.keys] + args.extras] : [args.keys, args.extras] }
61
62
 
62
- namespace name do
63
+ ns = @prefix ? "#{@prefix}:#{name}" : name
64
+ namespace ns do
63
65
  view = @command && @command != name ? @command : 'view'
64
66
  namespace view do
65
- if @mime['json'] && (exist? || !::Rake::Task.task_defined?("#{name}:#{view}:json"))
66
- desc format_desc(view, %w[json])
67
+ if @mime['json'] && (exist? || !::Rake::Task.task_defined?("#{ns}:#{view}:json"))
68
+ desc format_desc(view, 'json')
67
69
  task 'json', [:keys] do |_, args|
68
70
  read_keys(JSON, 'json', *params.(args))
69
71
  end
70
72
  end
71
73
 
72
- if @mime['yaml'] && (exist? || !::Rake::Task.task_defined?("#{name}:#{view}:yaml"))
73
- desc format_desc(view, %w[yaml yml])
74
+ if @mime['yaml'] && (exist? || !::Rake::Task.task_defined?("#{ns}:#{view}:yaml"))
75
+ desc format_desc(view, 'yaml', 'yml')
74
76
  task 'yaml', [:keys] do |_, args|
75
77
  require 'yaml'
76
78
  read_keys(YAML, 'yaml', *params.(args), ext: %w[yml yaml])
@@ -91,8 +93,9 @@ module Squared
91
93
  obj = eval(parse)
92
94
  ext << type if (ext = as_a(ext)).empty?
93
95
  file = realpath if file.nil? && exist?
94
- namespace name do
95
- desc format_desc(command, ext, exist: exist)
96
+
97
+ namespace(@prefix ? "#{@prefix}:#{name}" : name) do
98
+ desc format_desc(command, *ext, exist: exist)
96
99
  namespace command do
97
100
  task type, [:keys] do |_, args|
98
101
  if file
@@ -158,7 +161,7 @@ module Squared
158
161
  !@required || (!project.nil? && project.enabled?)
159
162
  end
160
163
 
161
- protected
164
+ private
162
165
 
163
166
  def read_keys(reader, type, file, keys, ext: [type])
164
167
  if (mime = mime_type(file)) && base_path(file).exist?
@@ -224,7 +227,7 @@ module Squared
224
227
  end
225
228
  end
226
229
  rescue StandardError
227
- project&.log&.warn "#{Viewer}(#{type}) => #{file ? "#{file} " : ''}{#{key}: undefined}"
230
+ project&.log&.warn "#{Viewer}(#{type}) => #{file && "#{file} "}{#{key}: undefined}"
228
231
  val = Regexp.escape($!.message)
229
232
  key = key.sub(/(#{val})\.|\.(#{val})|(#{val})/) do
230
233
  s = "<#{$3 || $2 || $1}>"
@@ -262,8 +265,9 @@ module Squared
262
265
  end
263
266
  end
264
267
 
265
- def format_desc(command, ext, exist: exist?)
266
- message(name, command, "#{ext.first}[#{exist ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys*]")
268
+ def format_desc(command, *ext, exist: exist?)
269
+ message(@prefix || '', *name.split(':'), command,
270
+ "#{ext.first}[#{exist ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys*]")
267
271
  end
268
272
 
269
273
  def realpath
@@ -283,7 +287,7 @@ module Squared
283
287
  end
284
288
 
285
289
  def warning?
286
- project && defined?(project.warning) == 'method' ? project.warning : true
290
+ project ? project.workspace.warning : true
287
291
  end
288
292
  end
289
293
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.0.7'
4
+ VERSION = '0.0.8'
5
5
  end
@@ -7,58 +7,45 @@ module Squared
7
7
  include Format
8
8
  include ::Rake::DSL
9
9
 
10
- TASK_BASE = {
11
- build: [],
12
- refresh: [],
13
- depend: [],
14
- outdated: [],
15
- doc: [],
16
- test: [],
17
- copy: [],
18
- clean: []
19
- }
20
- TASK_EXTEND = {}
21
- WORKSPACE_KEYS = TASK_BASE.keys.freeze
22
- private_constant :TASK_BASE, :TASK_EXTEND
23
-
24
10
  class << self
25
11
  def implement(*objs)
26
12
  objs.each do |obj|
27
- next unless obj < Project::Base
28
-
29
- project_kind.unshift(obj)
30
- obj.tasks&.each do |val|
31
- TASK_BASE[val] ||= []
32
- (TASK_EXTEND[val] ||= []).push(obj)
13
+ if obj < Project::Base
14
+ @impl_project.unshift(obj)
15
+ obj.tasks&.each { |task| @impl_series.add(task, obj) }
16
+ elsif obj < Workspace::Series
17
+ @impl_series = obj
33
18
  end
34
19
  end
35
20
  end
36
21
 
37
- def find(path: nil, ref: nil)
38
- if ref.is_a?(::Symbol) || ref.is_a?(::String)
39
- ret = project_kind.find { |proj| proj.ref == ref.to_sym }
40
- return ret if ret
22
+ def find(ref = nil, path: nil)
23
+ if ref && (ret = impl_project.find { |proj| proj.ref == ref.to_sym })
24
+ ret
25
+ elsif path
26
+ impl_project.find { |proj| proj.is_a?(path) }
41
27
  end
42
- project_kind.find { |proj| proj.is_a?(path) } if path
43
28
  end
44
29
 
45
30
  def to_s
46
31
  super.to_s.match(/[^:]+$/)[0]
47
32
  end
48
33
 
49
- attr_reader :project_kind
34
+ attr_reader :impl_project, :impl_series
50
35
  end
51
36
 
52
- @project_kind = []
37
+ @impl_project = []
38
+ @impl_series = Workspace::Series
53
39
 
54
- attr_reader :main, :root, :home, :series, :theme
40
+ attr_reader :root, :home, :main, :prefix, :series, :theme
55
41
  attr_accessor :exception, :warning, :pipe, :verbose
56
42
 
57
- def initialize(main, *, exception: false, pipe: false, verbose: nil, **kwargs)
58
- @main = main.to_s
59
- @home = Pathname.pwd
43
+ def initialize(home = Dir.pwd, *, main: nil, prefix: nil, exception: false, pipe: false, verbose: nil, **kwargs)
44
+ @home = (home = Pathname.new(home)).realdirpath
45
+ @main = (main || home.basename).to_s
60
46
  @root = @home.parent
61
- @series = Series.new(TASK_BASE)
47
+ @prefix = prefix
48
+ @series = Application.impl_series.new(prefix)
62
49
  @project = {}
63
50
  @extensions = []
64
51
  @script = {
@@ -66,42 +53,56 @@ module Squared
66
53
  ref: {},
67
54
  build: nil,
68
55
  dev: nil,
69
- prod: nil
56
+ prod: nil,
57
+ env: false
70
58
  }
71
- @theme = kwargs.key?(:common) && !kwargs[:common] ? {} : __get__(:theme)[:workspace]
72
59
  @exception = exception.is_a?(String) ? !env(exception, ignore: '0').nil? : exception
73
60
  @pipe = pipe.is_a?(String) ? !env(pipe, ignore: '0').nil? : pipe
74
61
  @verbose = verbose.nil? ? !@pipe : verbose
75
62
  @warning = @verbose
76
- __set__(:no_color, true) if @pipe
63
+ if kwargs.fetch(:common, true)
64
+ @theme = __get__(:theme)[:workspace]
65
+ __set__(:no_color, true) if @pipe
66
+ else
67
+ @theme = {}
68
+ end
77
69
  end
78
70
 
79
71
  def build(**kwargs)
72
+ kwargs[:parallel] = kwargs.fetch(:parallel, []).map(&:to_s)
80
73
  return unless enabled?
81
74
 
82
75
  @project.each_value do |proj|
83
76
  next unless proj.enabled?
84
77
 
85
78
  proj.populate(**kwargs)
86
- series.populate(proj)
79
+ series.__populate__(proj)
87
80
  end
88
81
 
89
- Application.project_kind.each { |obj| obj.populate(self, **kwargs) }
82
+ Application.impl_project.each { |obj| obj.populate(self, **kwargs) }
90
83
  @extensions.each { |ext| __send__(ext, **kwargs) }
91
84
 
85
+ series.__build__(**kwargs)
92
86
  __build__(**kwargs)
93
- series.build(**kwargs)
94
87
 
95
88
  yield self if block_given?
96
89
  end
97
90
 
98
- def with(group: nil, ref: nil)
91
+ def with(group: nil, ref: nil, &blk)
99
92
  @group = nil
100
93
  @ref = nil
101
94
  if group
102
95
  @group = group
96
+ if block_given?
97
+ instance_eval(&blk)
98
+ @group = nil
99
+ end
103
100
  elsif ref
104
101
  @ref = ref
102
+ if block_given?
103
+ instance_eval(&blk)
104
+ @ref = nil
105
+ end
105
106
  end
106
107
  self
107
108
  end
@@ -126,6 +127,10 @@ module Squared
126
127
  script_command :test, script, group, ref
127
128
  end
128
129
 
130
+ def exclude(base, group: @group, ref: @ref)
131
+ script_command :exclude, as_a(base, :to_sym).freeze, group, ref
132
+ end
133
+
129
134
  def add(name, path = nil, **kwargs)
130
135
  ref = if kwargs.key?(:ref)
131
136
  kwargs.delete(:ref)
@@ -135,10 +140,10 @@ module Squared
135
140
  kwargs[:group] = @group if !kwargs.key?(:group) && !@group.is_a?(::Array)
136
141
  path = root_path(path || name.to_s)
137
142
  proj = ((if !ref.is_a?(::Class)
138
- Application.find(path: path, ref: ref)
143
+ Application.find(ref, path: path)
139
144
  elsif ref < Project::Base
140
145
  ref
141
- end) || Project::Base).new(name, path, self, **kwargs)
146
+ end) || Project::Base).new(prefix ? "#{prefix}:#{name}" : name, path, self, **kwargs)
142
147
  @project[name = name.to_sym] = proj
143
148
  __get__(:project)[name] = proj unless kwargs[:private]
144
149
  self
@@ -177,31 +182,35 @@ module Squared
177
182
  def style(name, *args, target: nil, empty: false)
178
183
  data = nil
179
184
  if target
180
- as_a(target).each_with_index do |val, i|
185
+ as_a(target).each_with_index do |key, i|
181
186
  if i == 0
182
- break unless (data = __get__(:theme)[val.to_sym])
187
+ break unless (data = __get__(:theme)[key.to_sym])
183
188
  else
184
- data = data[val.to_sym] ||= {}
189
+ data = data[key.to_sym] ||= {}
185
190
  end
186
191
  end
187
- return unless data
188
192
  end
189
- apply_style(data || theme, name, *args, empty: empty)
193
+ apply_style(data || theme, name, *args, empty: empty) unless target && !data
190
194
  self
191
195
  end
192
196
 
193
- def script(group: nil, ref: nil)
197
+ def script(*args, group: nil, ref: nil)
194
198
  if group
195
199
  @script[:group][group.to_sym]
196
200
  elsif ref
197
201
  @script[:ref][ref.to_sym]
202
+ elsif (val = @script[:build])
203
+ r = @script[:ref][:_]
204
+ g = @script[:group][:_]
205
+ args.empty? || (!r && !g) || (r && args.include?(r)) || (g && args.include?(g)) ? [val, @script[:env]] : []
198
206
  else
199
- @script[:build]
207
+ []
200
208
  end
201
209
  end
202
210
 
203
211
  def env(key, default = nil, equals: nil, ignore: nil)
204
- ret = ENV.fetch("#{key}_#{main.gsub(/[^\w]+/, '_').upcase}", ENV[key]).to_s
212
+ @env ||= main.gsub(/[^\w]+/, '_').upcase
213
+ ret = ENV.fetch("#{key}_#{@env}", ENV[key]).to_s
205
214
  return ret == equals.to_s unless equals.nil?
206
215
 
207
216
  ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
@@ -216,7 +225,7 @@ module Squared
216
225
  end
217
226
 
218
227
  def find_base(obj)
219
- Application.project_kind.find { |proj| obj.instance_of?(proj) }
228
+ Application.impl_project.find { |proj| obj.instance_of?(proj) }
220
229
  end
221
230
 
222
231
  def to_s
@@ -234,14 +243,14 @@ module Squared
234
243
  def task_base?(key, val)
235
244
  return val if task_defined?(key)
236
245
 
237
- val if key == :refresh && series[:build].include?(val = "#{val.split(':').first}:build")
246
+ val if key == :refresh && series.build.include?(val = "#{val.split(':').first}:build")
238
247
  end
239
248
 
240
- def task_include?(obj, key)
241
- TASK_EXTEND.fetch(key, []).any? { |item| obj.is_a?(item) }
249
+ def task_extend?(obj, key)
250
+ series.extend?(obj, key)
242
251
  end
243
252
 
244
- def task_defined?(key)
253
+ def task_defined?(key, *)
245
254
  ::Rake::Task.task_defined?(key)
246
255
  end
247
256
 
@@ -258,45 +267,48 @@ module Squared
258
267
  private
259
268
 
260
269
  def __build__(**kwargs)
261
- if !task_defined?('default') && (default = kwargs[:default]) && !series.has?(default)
262
- task default: default
270
+ if !task_defined?('default') && (default = kwargs[:default]) && series.has?(default)
271
+ task 'default' => default
263
272
  end
264
- return unless series.has?('build')
273
+ return unless series.has?(:build)
265
274
 
266
- if (refresh = series[:refresh]).all? { |val| val.end_with?(':build') }
267
- refresh.clear
268
- end
269
- init = ['depend', dev? && series.has?('refresh') ? 'refresh' : 'build']
275
+ series.refresh.clear unless series.refresh.any? { |val| val.end_with?(':refresh') }
270
276
 
271
- task default: init[1] unless task_defined?('default')
277
+ init = [:depend, dev? && series.has?(:refresh) ? :refresh : :build]
278
+
279
+ task 'default' => init[1] unless task_defined?('default')
272
280
 
273
281
  return if task_defined?('init') || !series.has?(init[0])
274
282
 
275
283
  desc 'init'
276
- task init: init
284
+ task 'init' => init
277
285
  end
278
286
 
279
287
  def script_command(task, val, group, ref)
280
288
  if group
281
289
  label = :group
282
- items = as_a(group)
290
+ items = as_a(group, :to_sym)
283
291
  else
284
292
  label = :ref
285
- items = as_a(ref)
293
+ items = as_a(ref, :to_sym)
286
294
  end
287
- items.each { |name| (@script[label][name.to_sym] ||= {})[task] = val }
295
+ items.each { |name| (@script[label][name] ||= {})[task] = val }
288
296
  self
289
297
  end
290
298
 
291
299
  def script?(state, script: nil, pat: nil, ref: nil, group: nil, global: false)
292
- gr = @script[:ref][:_]
293
- gg = @script[:group][:_]
294
- if global && ((!ref && !group) || (!gr && !gg) || (ref && ref == gr) || (group && group == gg))
300
+ r = @script[:ref][:_]
301
+ g = @script[:group][:_]
302
+ if global && ((!ref && !group) || (!r && !g) || (ref && contains?(r, ref)) || (group && contains?(g, group)))
295
303
  pat = @script[state] if pat.nil?
296
304
  script ||= @script[:build]
297
305
  end
298
306
  pat.is_a?(::Regexp) ? pat.match?(script) : pat == true
299
307
  end
308
+
309
+ def contains?(data, val)
310
+ as_a(data).any? { |item| item.to_s == val.to_s }
311
+ end
300
312
  end
301
313
  end
302
314
  end