alpacabuildtool 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +48 -0
  3. data/.rubocop.yml +12 -0
  4. data/.semver +6 -0
  5. data/.travis.yml +10 -0
  6. data/CHANGELOG +18 -0
  7. data/Gemfile +7 -0
  8. data/LICENSE +22 -0
  9. data/README.md +235 -0
  10. data/README.rdoc +39 -0
  11. data/Rakefile +74 -0
  12. data/alpacabuildtool.gemspec +34 -0
  13. data/alpacabuildtool.rdoc +5 -0
  14. data/alpacabuildtool.todo +9 -0
  15. data/bin/alpaca +142 -0
  16. data/features/alpaca.feature +8 -0
  17. data/features/step_definitions/alpaca_steps.rb +13 -0
  18. data/features/step_definitions/visual_studio_solutions_steps.rb +47 -0
  19. data/features/support/env.rb +10 -0
  20. data/features/visual_studio_solutions.feature +43 -0
  21. data/lib/alpacabuildtool.rb +4 -0
  22. data/lib/alpacabuildtool/application.rb +195 -0
  23. data/lib/alpacabuildtool/configuration.rb +209 -0
  24. data/lib/alpacabuildtool/data/.alpaca.conf +148 -0
  25. data/lib/alpacabuildtool/data/doom.flf +826 -0
  26. data/lib/alpacabuildtool/data/logo.jpg +0 -0
  27. data/lib/alpacabuildtool/entities/nuspec.rb +107 -0
  28. data/lib/alpacabuildtool/entities/project.rb +54 -0
  29. data/lib/alpacabuildtool/entities/solution.rb +104 -0
  30. data/lib/alpacabuildtool/entities/xml.rb +41 -0
  31. data/lib/alpacabuildtool/entities/xml_node.rb +75 -0
  32. data/lib/alpacabuildtool/log/font.rb +92 -0
  33. data/lib/alpacabuildtool/log/log.rb +15 -0
  34. data/lib/alpacabuildtool/log/rainbowify_formatter.rb +70 -0
  35. data/lib/alpacabuildtool/log/rainbowify_logger.rb +47 -0
  36. data/lib/alpacabuildtool/managers/build_manager.rb +32 -0
  37. data/lib/alpacabuildtool/managers/package_manager.rb +136 -0
  38. data/lib/alpacabuildtool/managers/report_manager.rb +33 -0
  39. data/lib/alpacabuildtool/managers/test_manager.rb +35 -0
  40. data/lib/alpacabuildtool/os.rb +29 -0
  41. data/lib/alpacabuildtool/package_types/project_package.rb +44 -0
  42. data/lib/alpacabuildtool/package_types/tool_package.rb +53 -0
  43. data/lib/alpacabuildtool/tools/git.rb +22 -0
  44. data/lib/alpacabuildtool/tools/msbuild.rb +29 -0
  45. data/lib/alpacabuildtool/tools/nuget.rb +49 -0
  46. data/lib/alpacabuildtool/tools/nunit.rb +28 -0
  47. data/lib/alpacabuildtool/tools/nunit_orange.rb +18 -0
  48. data/lib/alpacabuildtool/tools/open_cover.rb +29 -0
  49. data/lib/alpacabuildtool/tools/report_generator.rb +25 -0
  50. data/lib/alpacabuildtool/tools/tool.rb +84 -0
  51. data/lib/alpacabuildtool/tools/wrapper.rb +66 -0
  52. data/lib/alpacabuildtool/versioning/version.rb +163 -0
  53. data/lib/alpacabuildtool/versioning/versioning.rb +84 -0
  54. data/spec/lib/alpacabuildtool/configuration_spec.rb +201 -0
  55. data/spec/lib/alpacabuildtool/entities/xml_spec.rb +39 -0
  56. data/spec/lib/alpacabuildtool/versioning/version_spec.rb +86 -0
  57. data/spec/lib/alpacabuildtool/versioning/versioning_spec.rb +194 -0
  58. data/spec/spec_helper.rb +3 -0
  59. data/spec/support/coverage.rb +26 -0
  60. data/test_data/sln1/.alpaca.conf +11 -0
  61. data/test_data/sln1/.semver +6 -0
  62. data/test_data/sln1/TestSolution.sln +22 -0
  63. data/test_data/sln1/TestSolution/App.config +6 -0
  64. data/test_data/sln1/TestSolution/Program.cs +16 -0
  65. data/test_data/sln1/TestSolution/Properties/AssemblyInfo.cs +36 -0
  66. data/test_data/sln1/TestSolution/TestSolution.csproj +59 -0
  67. data/test_data/sln2/.alpaca.conf +8 -0
  68. data/test_data/sln2/.semver +6 -0
  69. data/test_data/sln2/ProjectName/ProjectName.csproj +54 -0
  70. data/test_data/sln2/ProjectName/Properties/AssemblyInfo.cs +36 -0
  71. data/test_data/sln2/ProjectName/SomeFolderInProject/SomeClass.cs +16 -0
  72. data/test_data/sln2/ProjectName2/ProjectName2.csproj +58 -0
  73. data/test_data/sln2/ProjectName2/Properties/AssemblyInfo.cs +37 -0
  74. data/test_data/sln2/SolutionName.sln +34 -0
  75. data/test_data/sln2/Unit.Tests/Properties/AssemblyInfo.cs +36 -0
  76. data/test_data/sln2/Unit.Tests/SomeClassTests.cs +21 -0
  77. data/test_data/sln2/Unit.Tests/Unit.Tests.csproj +65 -0
  78. data/test_data/sln2/Unit.Tests/packages.config +4 -0
  79. data/test_data/sln3/TestSolution.nobuild.sln +22 -0
  80. data/test_data/sln3/TestSolution/App.config +6 -0
  81. data/test_data/sln3/TestSolution/Program.cs +16 -0
  82. data/test_data/sln3/TestSolution/Properties/AssemblyInfo.cs +36 -0
  83. data/test_data/sln3/TestSolution/TestSolution.nobuild.csproj +59 -0
  84. metadata +309 -0
@@ -0,0 +1,209 @@
1
+ require 'yaml'
2
+ require 'alpacabuildtool/os'
3
+
4
+ module AlpacaBuildTool
5
+ ##
6
+ # Cofniguration provides methods
7
+ # to retrieve from default, global and local configuration scopes
8
+ # and to save configuration into global or local scope
9
+ # - default configuration (<GEM>/lib/data/.alpaca.conf)
10
+ # - global configuration (~/.alpaca.conf)
11
+ # - local configuration (<SOLUTION_FOLDER>/.alpaca.conf)
12
+ class Configuration
13
+ ##
14
+ # Used to find default configuration
15
+ DATA_DIR = File.join(File.expand_path(File.dirname(__FILE__)), 'data')
16
+
17
+ ##
18
+ # Default configuration file with absolute path
19
+ DEFAULT_CONFIGURATION = File.join(DATA_DIR, '.alpaca.conf')
20
+
21
+ ##
22
+ # Global configuration file with absolute path
23
+ GLOBAL_CONFIGURATION = File.expand_path('~/.alpaca.conf')
24
+
25
+ ##
26
+ # Use to define relative path to local configuration from solution
27
+ LOCAL_CONFIGURATION_PROPERTY = 'local_configuration'
28
+
29
+ ##
30
+ # Use in configuration values and in result it will be replaced with
31
+ # solution name
32
+ SOLUTION_NAME_VARIABLE = '#{solution_name}'
33
+
34
+ ##
35
+ # Use in configuration values and in result it will be replaced with
36
+ # solution directory path
37
+ SOLUTION_DIR_VARIABLE = '#{solution_directory}'
38
+
39
+ ##
40
+ # Use this key to clean configuration entry
41
+ #
42
+ # #>global configuration:
43
+ # # MSBuild:
44
+ # # options:
45
+ # # target: ["Clean", "Rebuild"]
46
+ # # verbosity: "minimal"
47
+ # # nologo: true
48
+ #
49
+ # #>local configuration:
50
+ # # MSBuild:
51
+ # # options:
52
+ # # clean_configuration: true
53
+ # # nologo: true
54
+ #
55
+ # #>results:
56
+ # # MSBuild:
57
+ # # options:
58
+ # # nologo: true
59
+ CLEAN_CONFIGURATION_KEY = 'clean_configuration'
60
+
61
+ ##
62
+ # Saves list of properties into global scope configuration
63
+ #
64
+ # +properties+:: Array of properties 'path.to.property=value'
65
+ def self.set(properties)
66
+ file = File.expand_path GLOBAL_CONFIGURATION
67
+ File.new(file, 'w+').close unless File.exist? file
68
+ config = YAML.load(File.open(file)) || {}
69
+ properties.each { |property| set_property(config, property) }
70
+ File.open(file, 'w+') { |f| f.write config.to_yaml }
71
+ end
72
+
73
+ ##
74
+ # Set one property for existing configuration
75
+ #
76
+ # +config+:: hash to hold new property
77
+ # +property+:: property _node1.node2=value_
78
+ #
79
+ # Configuration.set_propert(hash, 'node1.node2=value')
80
+ # # will make hash['node1']['node2'] == value
81
+ # # and create node1 or node2 if they do not exist there
82
+ def self.set_property(config, property)
83
+ name, value = property.split('=')
84
+ nodes = name.split('.')
85
+ tail = nodes.last
86
+ current_node = config
87
+ nodes.each do |node|
88
+ current_node[node] ||= {}
89
+ current_node[node] = value if node == tail
90
+ current_node = current_node[node]
91
+ end
92
+ end
93
+
94
+ ##
95
+ # Merges hashes recursively with higher priority
96
+ # for second hash
97
+ # Also second config can contain
98
+ #
99
+ # clean_configuration: true
100
+ #
101
+ # that will force to take only second configuration content
102
+ # for that configuration level
103
+ #
104
+ # +first_config+:: low priority configuration (hash)
105
+ # +second_config+:: high priority configuration
106
+ def self.merge(first_config, second_config)
107
+ return clean(second_config) if clean?(second_config)
108
+ first_config.merge(second_config) do |_key, old_value, new_value|
109
+ old_value.is_a?(Hash) ? merge(old_value, new_value) : new_value
110
+ end
111
+ end
112
+
113
+ ##
114
+ # Removes *clean_configuration* entry for the hash
115
+ #
116
+ # +hash+:: hash to be cleaned
117
+ def self.clean(hash)
118
+ hash.delete CLEAN_CONFIGURATION_KEY
119
+ hash
120
+ end
121
+
122
+ ##
123
+ # Check if hash has *clean_configuration* entry
124
+ #
125
+ # +hash+:: hash to be verified
126
+ def self.clean?(hash)
127
+ hash.key? CLEAN_CONFIGURATION_KEY
128
+ end
129
+
130
+ ##
131
+ # Creates instance of local configuration
132
+ #
133
+ # +solution+:: solution object to find configuration for
134
+ def initialize(solution)
135
+ local_config = load_local_configuration(solution.dir)
136
+ @configuration = Configuration.merge(global_config, local_config)
137
+ @configuration = detokenize(@configuration, solution)
138
+ end
139
+
140
+ ##
141
+ # Saves list of properties into local scope configuration
142
+ #
143
+ # +properties+:: Array of properties 'path.to.property=value'
144
+ def set(properties)
145
+ File.new(@file, 'w+').close unless File.exist? @file
146
+ config = YAML.load(File.open(@file)) || {}
147
+ properties.each do |property|
148
+ Configuration.set_property(config, property)
149
+ end
150
+ File.open(@file, 'w+') { |f| f.write config.to_yaml }
151
+ end
152
+
153
+ ##
154
+ # Returns hash with configuration for entry
155
+ #
156
+ # +entry+:: entry name
157
+ def [](entry)
158
+ @configuration[entry]
159
+ end
160
+
161
+ private
162
+
163
+ def global_config
164
+ if Configuration.class_variable_defined? '@@global_configuration'
165
+ return Marshal.load(Marshal.dump(@@global_configuration))
166
+ end
167
+ @@global_configuration = load_global_configuration
168
+ end
169
+
170
+ def load_global_configuration
171
+ default_config = YAML.load(File.open(DEFAULT_CONFIGURATION)) || {}
172
+ if File.exist?(GLOBAL_CONFIGURATION)
173
+ global_conf = YAML.load(File.open(GLOBAL_CONFIGURATION)) || {}
174
+ Configuration.merge(default_config, global_conf)
175
+ else
176
+ default_config
177
+ end
178
+ end
179
+
180
+ def load_local_configuration(solution_dir)
181
+ config_path = global_config[LOCAL_CONFIGURATION_PROPERTY]
182
+ @file = File.expand_path(File.join(solution_dir, config_path))
183
+ return {} unless File.exist? @file
184
+ YAML.load(File.open(@file)) || {}
185
+ end
186
+
187
+ def detokenize(config, solution)
188
+ config = detokenize_os(config) if config.is_a? Hash
189
+ return detokenize_string(config, solution) if config.is_a? String
190
+ return config.map { |i| detokenize(i, solution) } if config.is_a? Array
191
+ return detokenize_hash(config, solution) if config.is_a? Hash
192
+ config
193
+ end
194
+
195
+ def detokenize_os(value)
196
+ (value.is_a?(Hash) && value[Os.os]) ? value[Os.os] : value
197
+ end
198
+
199
+ def detokenize_string(value, solution)
200
+ value = value.gsub(SOLUTION_DIR_VARIABLE, solution.dir)
201
+ value.gsub(SOLUTION_NAME_VARIABLE, File.basename(solution.file, '.*'))
202
+ end
203
+
204
+ def detokenize_hash(value, solution)
205
+ value.keys.each { |key| value[key] = detokenize(value[key], solution) }
206
+ value
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,148 @@
1
+ # type: yaml
2
+ # ==================================
3
+ # General tips
4
+ # ----------------------------------
5
+ # 1. Everywhere you can use OS specific configuration for string values by using
6
+ # :windows, :macos, :linux, :unix etc entries:
7
+ # exe:
8
+ # :windows: c:\path\cool.exe
9
+ # :linux: /home/name/path/cool
10
+ # 2. Everywhere in strings you can use variables #{solution_directory} and
11
+ # #{solution_name}
12
+ # Nuget:
13
+ # exe: "#{solution_directory}/.nuget/nuget.exe"
14
+ # 3. Use 'clean_configuration' to clean value of hash entry
15
+ # MSBuild:
16
+ # options:
17
+ # clean_configuration: true
18
+ # target: ["Build"]
19
+ # ==================================
20
+
21
+ # 'local_configuration' set relative path from solution where local
22
+ # configuration stored. By default it is '.alpaca.conf' file near *.sln
23
+ local_configuration: '.alpaca.conf'
24
+
25
+ # 'no_build' set array of tags that mark solution as no build solutions.
26
+ # By default solutions that contains '.nobuild' string in the name will not
27
+ # be built/packaged or any other changes not going to be processed
28
+ no_build: ['.nobuild']
29
+
30
+ # 'project_types' set array of project types for tests. Type can be used from
31
+ # command line interface for 'test' command and 'name' is a string that project
32
+ # name should contain(note that it's a name and not file name or path)
33
+ project_types:
34
+ - type: unit
35
+ name: Unit.Tests
36
+ - type: service
37
+ name: Service.Tests
38
+
39
+ # You can set 'all_packages' in global configuration so you don't need to store
40
+ # shared fields in each package configuration. Note that local configuration
41
+ # can still override any entry for example you can set global source to
42
+ # nuget.org but for some specific solution override it to your own feed
43
+ #
44
+ # ```
45
+ # all_packages:
46
+ # authors: ['Vasyl', 'Kate']
47
+ # owners: ['Vasyl', 'Kate']
48
+ # projectUrl: https://github.com/vasyl-purchel/alpaca
49
+ # iconUrl: 'https://raw.githubusercontent.com/vasyl-purchel/alpaca/master/lib/alpacabuildtool/data/logo.jpg'
50
+ # requireLicenseAcceptance: false
51
+ # language: en-GB
52
+ # source: nuget.org
53
+ # ```
54
+
55
+ # ==================================
56
+ # Tools are configured in such way that you can use 'absolute path to exe' or
57
+ # just name of executable file if it is accessible in ENV['PATH'] or use nuget
58
+ # package to download it(this is not applies to MSBuild and Nuget tools)
59
+ # ==================================
60
+
61
+ # 'MSBuild' set configuration for MSBuild
62
+ # 'exe' - msbuild executable file
63
+ # 'options' - command line options for msbuild.
64
+ # Full list is [here](https://msdn.microsoft.com/en-us/library/ms164311.aspx)
65
+ MSBuild:
66
+ exe: 'C:\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe'
67
+ options:
68
+ target: ["Clean", "Rebuild"]
69
+ verbosity: "minimal"
70
+ nologo: true
71
+
72
+ # 'Nuget' set configuration for Nuget
73
+ # 'exe' - path to nuget.exe
74
+ # 'options' - shared options for all commands
75
+ # 'commands' - configuration for each command
76
+ # Full list is [here](https://docs.nuget.org/consume/command-line-reference)
77
+ Nuget:
78
+ exe:
79
+ :windows: 'C:\Nuget\Nuget.exe'
80
+ :linux: 'mono --runtime=v4.0.30319 /usr/lib/nuget/nuget.exe'
81
+ options:
82
+ NonInteractive: true
83
+ commands:
84
+ pack:
85
+ NoPackageAnalysis: true
86
+ Symbols: true
87
+ OutputDirectory: "#{solution_directory}/.output/"
88
+
89
+ # 'NUnit' set configuration for NUnit
90
+ # if nunit-console.exe is not accessible via ENV['PATH'] then it will be
91
+ # downloaded(unless you override 'exe' to absolute path) via nuget package
92
+ #
93
+ # AutoDownload configured with 'package_id', 'pre_release'(to use release or
94
+ # pre-release versions also)
95
+ # By default nunit use pre-release version and for time writting it was 3.0-beta
96
+ # Note: if you want to use 2.6 version then you need to modify nunit tool
97
+ # as current release and pre-release versions for nunit-console use different
98
+ # options style(msdos and unix like styles - /option or --option)
99
+ #
100
+ # 'options' - set command line options, for the full list take a look
101
+ # [here](http://nunit.org/index.php?p=consoleCommandLine&r=3.0)
102
+ NUnit:
103
+ exe: nunit-console.exe
104
+ package_id: NUnit.Console
105
+ pre_release: true
106
+ options:
107
+ noheader: true
108
+ process: Multiple
109
+ work: "#{solution_directory}/.tests"
110
+ config: Release
111
+ output: "#{solution_directory}/.tests/tests.log"
112
+ result: "#{solution_directory}/.tests/UnitTestsResult.xml;format=nunit3"
113
+
114
+ # 'OpenCover' set configuration for OpenCover same to NUnit with AutoDownload
115
+ # but it use specific variables #{EXE} and #{ARGS} to put inner tool(nunit)
116
+ # exe and arguments for tests to wrap them to check coverage
117
+ OpenCover:
118
+ exe: opencover.console.exe
119
+ package_id: OpenCover
120
+ pre_release: false
121
+ options:
122
+ register: user
123
+ target: "#{EXE}"
124
+ targetargs: "#{ARGS}"
125
+ mergebyhash: true
126
+ output: "#{solution_directory}/.tests/coverage.xml"
127
+
128
+ # 'NUnitOrange' set configuration for NUnitOrange same to NUnit with
129
+ # AutoDownload but it is not using options as nunitorange.exe interface take
130
+ # 2 arguments - input and output file names to convert reports
131
+ NUnitOrange:
132
+ exe: nunitorange.exe
133
+ package_id: NUnitOrange
134
+ pre_release: false
135
+ input: "#{solution_directory}/.tests/UnitTestsResult.xml"
136
+ output: "#{solution_directory}/.tests/UnitTestsResult.html"
137
+
138
+ # 'ReportGenerator' set configuration for ReportGenerator same to NUnit with
139
+ # AutoDownload and options
140
+ ReportGenerator:
141
+ exe: ReportGenerator.exe
142
+ package_id: ReportGenerator
143
+ pre_release: false
144
+ options:
145
+ reports: "#{solution_directory}/.tests/coverage.xml"
146
+ targetdir: "#{solution_directory}/.tests"
147
+ verbosity: Info
148
+ reporttypes: Html
@@ -0,0 +1,826 @@
1
+ $ 8
2
+ $@
3
+ $@
4
+ $@
5
+ $@
6
+ $@
7
+ $@
8
+ $@
9
+ $@@
10
+ _ @
11
+ | |@
12
+ | |@
13
+ | |@
14
+ |_|@
15
+ (_)@
16
+ @
17
+ @@
18
+ _ _ @
19
+ ( | )@
20
+ V V @
21
+ $ @
22
+ $ @
23
+ $ @
24
+ @
25
+ @@
26
+ _ _ @
27
+ _| || |_ @
28
+ |_ __ _|@
29
+ _| || |_ @
30
+ |_ __ _|@
31
+ |_||_| @
32
+ @
33
+ @@
34
+ _ @
35
+ | | @
36
+ / __)@
37
+ \__ \@
38
+ ( /@
39
+ |_| @
40
+ @
41
+ @@
42
+ _ __@
43
+ (_) / /@
44
+ / / @
45
+ / / @
46
+ / / _ @
47
+ /_/ (_)@
48
+ @
49
+ @@
50
+ @
51
+ ___ @
52
+ ( _ ) @
53
+ / _ \/\@
54
+ | (_> <@
55
+ \___/\/@
56
+ @
57
+ @@
58
+ _ @
59
+ ( )@
60
+ |/ @
61
+ $ @
62
+ $ @
63
+ $ @
64
+ @
65
+ @@
66
+ __@
67
+ / /@
68
+ | | @
69
+ | | @
70
+ | | @
71
+ | | @
72
+ \_\@
73
+ @@
74
+ __ @
75
+ \ \ @
76
+ | |@
77
+ | |@
78
+ | |@
79
+ | |@
80
+ /_/ @
81
+ @@
82
+ _ @
83
+ /\| |/\ @
84
+ \ ` ' / @
85
+ |_ _|@
86
+ / , . \ @
87
+ \/|_|\/ @
88
+ @
89
+ @@
90
+ @
91
+ _ @
92
+ _| |_ @
93
+ |_ _|@
94
+ |_| @
95
+ $ @
96
+ @
97
+ @@
98
+ @
99
+ @
100
+ @
101
+ @
102
+ _ @
103
+ ( )@
104
+ |/ @
105
+ @@
106
+ @
107
+ @
108
+ ______ @
109
+ |______|@
110
+ $ @
111
+ $ @
112
+ @
113
+ @@
114
+ @
115
+ @
116
+ @
117
+ @
118
+ _ @
119
+ (_)@
120
+ @
121
+ @@
122
+ __@
123
+ / /@
124
+ / / @
125
+ / / @
126
+ / / @
127
+ /_/ @
128
+ @
129
+ @@
130
+ _____ @
131
+ | _ |@
132
+ | |/' |@
133
+ | /| |@
134
+ \ |_/ /@
135
+ \___/ @
136
+ @
137
+ @@
138
+ __ @
139
+ / | @
140
+ `| | @
141
+ | | @
142
+ _| |_@
143
+ \___/@
144
+ @
145
+ @@
146
+ _____ @
147
+ / __ \@
148
+ `' / /'@
149
+ / / @
150
+ ./ /___@
151
+ \_____/@
152
+ @
153
+ @@
154
+ _____ @
155
+ |____ |@
156
+ / /@
157
+ $ \ \@
158
+ .___/ /@
159
+ \____/ @
160
+ @
161
+ @@
162
+ ___ @
163
+ / |@
164
+ / /| |@
165
+ / /_| |@
166
+ \___ |@
167
+ |_/@
168
+ @
169
+ @@
170
+ _____ @
171
+ | ___|@
172
+ |___ \ @
173
+ \ \@
174
+ /\__/ /@
175
+ \____/ @
176
+ @
177
+ @@
178
+ ____ @
179
+ / ___|@
180
+ / /___ @
181
+ | ___ \@
182
+ | \_/ |@
183
+ \_____/@
184
+ @
185
+ @@
186
+ ______@
187
+ |___ /@
188
+ $/ / @
189
+ / / @
190
+ ./ / @
191
+ \_/ @
192
+ @
193
+ @@
194
+ _____ @
195
+ | _ |@
196
+ \ V / @
197
+ / _ \ @
198
+ | |_| |@
199
+ \_____/@
200
+ @
201
+ @@
202
+ _____ @
203
+ | _ |@
204
+ | |_| |@
205
+ \____ |@
206
+ .___/ /@
207
+ \____/ @
208
+ @
209
+ @@
210
+ @
211
+ _ @
212
+ (_)@
213
+ $ @
214
+ _ @
215
+ (_)@
216
+ @
217
+ @@
218
+ @
219
+ _ @
220
+ (_)@
221
+ $ @
222
+ _ @
223
+ ( )@
224
+ |/ @
225
+ @@
226
+ __@
227
+ / /@
228
+ / / @
229
+ < < @
230
+ \ \ @
231
+ \_\@
232
+ @
233
+ @@
234
+ @
235
+ ______ @
236
+ |______|@
237
+ ______ @
238
+ |______|@
239
+ @
240
+ @
241
+ @@
242
+ __ @
243
+ \ \ @
244
+ \ \ @
245
+ > >@
246
+ / / @
247
+ /_/ @
248
+ @
249
+ @@
250
+ ___ @
251
+ |__ \ @
252
+ ) |@
253
+ / / @
254
+ |_| @
255
+ (_) @
256
+ @
257
+ @@
258
+ @
259
+ ____ @
260
+ / __ \ @
261
+ / / _` |@
262
+ | | (_| |@
263
+ \ \__,_|@
264
+ \____/ @
265
+ @@
266
+ ___ @
267
+ / _ \ @
268
+ / /_\ \@
269
+ | _ |@
270
+ | | | |@
271
+ \_| |_/@
272
+ @
273
+ @@
274
+ ______ @
275
+ | ___ \@
276
+ | |_/ /@
277
+ | ___ \@
278
+ | |_/ /@
279
+ \____/ @
280
+ @
281
+ @@
282
+ _____ @
283
+ / __ \@
284
+ | / \/@
285
+ | | @
286
+ | \__/\@
287
+ \____/@
288
+ @
289
+ @@
290
+ ______ @
291
+ | _ \@
292
+ | | | |@
293
+ | | | |@
294
+ | |/ / @
295
+ |___/ @
296
+ @
297
+ @@
298
+ _____ @
299
+ | ___|@
300
+ | |__ @
301
+ | __| @
302
+ | |___ @
303
+ \____/ @
304
+ @
305
+ @@
306
+ ______ @
307
+ | ___|@
308
+ | |_ @
309
+ | _| @
310
+ | | @
311
+ \_| @
312
+ @
313
+ @@
314
+ _____ @
315
+ | __ \@
316
+ | | \/@
317
+ | | __ @
318
+ | |_\ \@
319
+ \____/@
320
+ @
321
+ @@
322
+ _ _ @
323
+ | | | |@
324
+ | |_| |@
325
+ | _ |@
326
+ | | | |@
327
+ \_| |_/@
328
+ @
329
+ @@
330
+ _____ @
331
+ |_ _|@
332
+ | | @
333
+ | | @
334
+ _| |_ @
335
+ \___/ @
336
+ @
337
+ @@
338
+ ___ @
339
+ |_ |@
340
+ $ | |@
341
+ | |@
342
+ /\__/ /@
343
+ \____/ @
344
+ @
345
+ @@
346
+ _ __@
347
+ | | / /@
348
+ | |/ / @
349
+ | \ @
350
+ | |\ \@
351
+ \_| \_/@
352
+ @
353
+ @@
354
+ _ @
355
+ | | $ @
356
+ | | $ @
357
+ | | @
358
+ | |____@
359
+ \_____/@
360
+ @
361
+ @@
362
+ ___ ___@
363
+ | \/ |@
364
+ | . . |@
365
+ | |\/| |@
366
+ | | | |@
367
+ \_| |_/@
368
+ @
369
+ @@
370
+ _ _ @
371
+ | \ | |@
372
+ | \| |@
373
+ | . ` |@
374
+ | |\ |@
375
+ \_| \_/@
376
+ @
377
+ @@
378
+ _____ @
379
+ | _ |@
380
+ | | | |@
381
+ | | | |@
382
+ \ \_/ /@
383
+ \___/ @
384
+ @
385
+ @@
386
+ ______ @
387
+ | ___ \@
388
+ | |_/ /@
389
+ | __/ @
390
+ | | @
391
+ \_| @
392
+ @
393
+ @@
394
+ _____ @
395
+ | _ |@
396
+ | | | |@
397
+ | | | |@
398
+ \ \/' /@
399
+ \_/\_\@
400
+ @
401
+ @@
402
+ ______ @
403
+ | ___ \@
404
+ | |_/ /@
405
+ | / @
406
+ | |\ \ @
407
+ \_| \_|@
408
+ @
409
+ @@
410
+ _____ @
411
+ / ___|@
412
+ \ `--. @
413
+ `--. \@
414
+ /\__/ /@
415
+ \____/ @
416
+ @
417
+ @@
418
+ _____ @
419
+ |_ _|@
420
+ | | @
421
+ | | @
422
+ | | @
423
+ \_/ @
424
+ @
425
+ @@
426
+ _ _ @
427
+ | | | |@
428
+ | | | |@
429
+ | | | |@
430
+ | |_| |@
431
+ \___/ @
432
+ @
433
+ @@
434
+ _ _ @
435
+ | | | |@
436
+ | | | |@
437
+ | | | |@
438
+ \ \_/ /@
439
+ \___/ @
440
+ @
441
+ @@
442
+ _ _ @
443
+ | | | |@
444
+ | | | |@
445
+ | |/\| |@
446
+ \ /\ /@
447
+ \/ \/ @
448
+ @
449
+ @@
450
+ __ __@
451
+ \ \ / /@
452
+ \ V / @
453
+ / \ @
454
+ / /^\ \@
455
+ \/ \/@
456
+ @
457
+ @@
458
+ __ __@
459
+ \ \ / /@
460
+ \ V / @
461
+ \ / @
462
+ | | @
463
+ \_/ @
464
+ @
465
+ @@
466
+ ______@
467
+ |___ /@
468
+ $/ / @
469
+ / / @
470
+ ./ /___@
471
+ \_____/@
472
+ @
473
+ @@
474
+ ___ @
475
+ | _|@
476
+ | | @
477
+ | | @
478
+ | | @
479
+ | |_ @
480
+ |___|@
481
+ @@
482
+ __ @
483
+ \ \ @
484
+ \ \ @
485
+ \ \ @
486
+ \ \ @
487
+ \_\@
488
+ @
489
+ @@
490
+ ___ @
491
+ |_ |@
492
+ | |@
493
+ | |@
494
+ | |@
495
+ _| |@
496
+ |___|@
497
+ @@
498
+ /\ @
499
+ |/\|@
500
+ $ @
501
+ $ @
502
+ $ @
503
+ $ @
504
+ @
505
+ @@
506
+ @
507
+ @
508
+ @
509
+ @
510
+ @
511
+ $ @
512
+ ______ @
513
+ |______|@@
514
+ _ @
515
+ ( )@
516
+ \|@
517
+ $ @
518
+ $ @
519
+ $ @
520
+ @
521
+ @@
522
+ @
523
+ @
524
+ __ _ @
525
+ / _` |@
526
+ | (_| |@
527
+ \__,_|@
528
+ @
529
+ @@
530
+ _ @
531
+ | | @
532
+ | |__ @
533
+ | '_ \ @
534
+ | |_) |@
535
+ |_.__/ @
536
+ @
537
+ @@
538
+ @
539
+ @
540
+ ___ @
541
+ / __|@
542
+ | (__ @
543
+ \___|@
544
+ @
545
+ @@
546
+ _ @
547
+ | |@
548
+ __| |@
549
+ / _` |@
550
+ | (_| |@
551
+ \__,_|@
552
+ @
553
+ @@
554
+ @
555
+ @
556
+ ___ @
557
+ / _ \@
558
+ | __/@
559
+ \___|@
560
+ @
561
+ @@
562
+ __ @
563
+ / _|@
564
+ | |_ @
565
+ | _|@
566
+ | | @
567
+ |_| @
568
+ @
569
+ @@
570
+ @
571
+ @
572
+ __ _ @
573
+ / _` |@
574
+ | (_| |@
575
+ \__, |@
576
+ __/ |@
577
+ |___/ @@
578
+ _ @
579
+ | | @
580
+ | |__ @
581
+ | '_ \ @
582
+ | | | |@
583
+ |_| |_|@
584
+ @
585
+ @@
586
+ _ @
587
+ (_)@
588
+ _ @
589
+ | |@
590
+ | |@
591
+ |_|@
592
+ @
593
+ @@
594
+ _ @
595
+ (_)@
596
+ _ @
597
+ | |@
598
+ | |@
599
+ | |@
600
+ _/ |@
601
+ |__/ @@
602
+ _ @
603
+ | | @
604
+ | | __@
605
+ | |/ /@
606
+ | < @
607
+ |_|\_\@
608
+ @
609
+ @@
610
+ _ @
611
+ | |@
612
+ | |@
613
+ | |@
614
+ | |@
615
+ |_|@
616
+ @
617
+ @@
618
+ @
619
+ @
620
+ _ __ ___ @
621
+ | '_ ` _ \ @
622
+ | | | | | |@
623
+ |_| |_| |_|@
624
+ @
625
+ @@
626
+ @
627
+ @
628
+ _ __ @
629
+ | '_ \ @
630
+ | | | |@
631
+ |_| |_|@
632
+ @
633
+ @@
634
+ @
635
+ @
636
+ ___ @
637
+ / _ \ @
638
+ | (_) |@
639
+ \___/ @
640
+ @
641
+ @@
642
+ @
643
+ @
644
+ _ __ @
645
+ | '_ \ @
646
+ | |_) |@
647
+ | .__/ @
648
+ | | @
649
+ |_| @@
650
+ @
651
+ @
652
+ __ _ @
653
+ / _` |@
654
+ | (_| |@
655
+ \__, |@
656
+ | |@
657
+ |_|@@
658
+ @
659
+ @
660
+ _ __ @
661
+ | '__|@
662
+ | | @
663
+ |_| @
664
+ @
665
+ @@
666
+ @
667
+ @
668
+ ___ @
669
+ / __|@
670
+ \__ \@
671
+ |___/@
672
+ @
673
+ @@
674
+ _ @
675
+ | | @
676
+ | |_ @
677
+ | __|@
678
+ | |_ @
679
+ \__|@
680
+ @
681
+ @@
682
+ @
683
+ @
684
+ _ _ @
685
+ | | | |@
686
+ | |_| |@
687
+ \__,_|@
688
+ @
689
+ @@
690
+ @
691
+ @
692
+ __ __@
693
+ \ \ / /@
694
+ \ V / @
695
+ \_/ @
696
+ @
697
+ @@
698
+ @
699
+ @
700
+ __ __@
701
+ \ \ /\ / /@
702
+ \ V V / @
703
+ \_/\_/ @
704
+ @
705
+ @@
706
+ @
707
+ @
708
+ __ __@
709
+ \ \/ /@
710
+ > < @
711
+ /_/\_\@
712
+ @
713
+ @@
714
+ @
715
+ @
716
+ _ _ @
717
+ | | | |@
718
+ | |_| |@
719
+ \__, |@
720
+ __/ |@
721
+ |___/ @@
722
+ @
723
+ @
724
+ ____@
725
+ |_ /@
726
+ / / @
727
+ /___|@
728
+ @
729
+ @@
730
+ __@
731
+ / /@
732
+ | | @
733
+ / / @
734
+ \ \ @
735
+ | | @
736
+ \_\@
737
+ @@
738
+ _ @
739
+ | |@
740
+ | |@
741
+ | |@
742
+ | |@
743
+ | |@
744
+ | |@
745
+ |_|@@
746
+ __ @
747
+ \ \ @
748
+ | | @
749
+ \ \@
750
+ / /@
751
+ | | @
752
+ /_/ @
753
+ @@
754
+ /\/|@
755
+ |/\/ @
756
+ $ @
757
+ $ @
758
+ $ @
759
+ $ @
760
+ @
761
+ @@
762
+ _ _ @
763
+ (_)_(_)@
764
+ / _ \ @
765
+ / /_\ \@
766
+ | _ |@
767
+ \_| |_/@
768
+ @
769
+ @@
770
+ _ _ @
771
+ (_)_(_)@
772
+ | _ |@
773
+ | | | |@
774
+ \ \_/ /@
775
+ \___/ @
776
+ @
777
+ @@
778
+ _ _ @
779
+ (_) (_)@
780
+ | | | |@
781
+ | | | |@
782
+ | |_| |@
783
+ \___/ @
784
+ @
785
+ @@
786
+ _ _ @
787
+ (_) (_)@
788
+ __ _ @
789
+ / _` |@
790
+ | (_| |@
791
+ \__,_|@
792
+ @
793
+ @@
794
+ _ _ @
795
+ (_) (_)@
796
+ ___ @
797
+ / _ \ @
798
+ | (_) |@
799
+ \___/ @
800
+ @
801
+ @@
802
+ _ _ @
803
+ (_) (_)@
804
+ _ _ @
805
+ | | | |@
806
+ | |_| |@
807
+ \__,_|@
808
+ @
809
+ @@
810
+ ___ @
811
+ / _ \ @
812
+ | | ) |@
813
+ | |< < @
814
+ | | ) |@
815
+ | ||_/ @
816
+ \_| @
817
+ @@
818
+ 0 ALPACA
819
+ ^ ^ @
820
+ (*w*) @
821
+ | | @
822
+ | +-+o@
823
+ \ / @
824
+ #-# @
825
+ @
826
+ @@