alpacabuildtool 1.0.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.
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
+ @@