copland 0.8.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 (184) hide show
  1. data/doc/README +88 -0
  2. data/doc/manual-html/chapter-1.html +454 -0
  3. data/doc/manual-html/chapter-10.html +399 -0
  4. data/doc/manual-html/chapter-11.html +600 -0
  5. data/doc/manual-html/chapter-12.html +406 -0
  6. data/doc/manual-html/chapter-2.html +382 -0
  7. data/doc/manual-html/chapter-3.html +424 -0
  8. data/doc/manual-html/chapter-4.html +432 -0
  9. data/doc/manual-html/chapter-5.html +381 -0
  10. data/doc/manual-html/chapter-6.html +364 -0
  11. data/doc/manual-html/chapter-7.html +434 -0
  12. data/doc/manual-html/chapter-8.html +373 -0
  13. data/doc/manual-html/chapter-9.html +324 -0
  14. data/doc/manual-html/copland.png +0 -0
  15. data/doc/manual-html/index.html +331 -0
  16. data/doc/manual-html/manual.css +179 -0
  17. data/doc/manual-html/tutorial-1.html +407 -0
  18. data/doc/manual-html/tutorial-2.html +451 -0
  19. data/doc/manual-html/tutorial-3.html +484 -0
  20. data/doc/manual-html/tutorial-4.html +446 -0
  21. data/doc/manual-html/tutorial-5.html +520 -0
  22. data/doc/manual/chapter.erb +18 -0
  23. data/doc/manual/example.erb +18 -0
  24. data/doc/manual/img/copland.png +0 -0
  25. data/doc/manual/index.erb +30 -0
  26. data/doc/manual/manual.css +179 -0
  27. data/doc/manual/manual.rb +239 -0
  28. data/doc/manual/manual.yml +2643 -0
  29. data/doc/manual/page.erb +102 -0
  30. data/doc/manual/tutorial.erb +30 -0
  31. data/doc/packages/copland.html +764 -0
  32. data/doc/packages/copland.lib.html +439 -0
  33. data/doc/packages/copland.remote.html +2096 -0
  34. data/doc/packages/copland.webrick.html +925 -0
  35. data/doc/packages/index.html +49 -0
  36. data/doc/packages/packrat.css +125 -0
  37. data/examples/calc/calc.rb +47 -0
  38. data/examples/calc/package.yml +35 -0
  39. data/examples/calc/services.rb +74 -0
  40. data/examples/solitaire-cipher/README +11 -0
  41. data/examples/solitaire-cipher/Rakefile +57 -0
  42. data/examples/solitaire-cipher/bin/main.rb +14 -0
  43. data/examples/solitaire-cipher/lib/cipher.rb +230 -0
  44. data/examples/solitaire-cipher/lib/cli.rb +24 -0
  45. data/examples/solitaire-cipher/lib/package.yml +106 -0
  46. data/examples/solitaire-cipher/test/tc_deck.rb +30 -0
  47. data/examples/solitaire-cipher/test/tc_key-stream.rb +19 -0
  48. data/examples/solitaire-cipher/test/tc_keying-algorithms.rb +31 -0
  49. data/examples/solitaire-cipher/test/tc_solitaire-cipher.rb +66 -0
  50. data/examples/solitaire-cipher/test/tc_unkeyed-algorithm.rb +17 -0
  51. data/examples/solitaire-cipher/test/tests.rb +2 -0
  52. data/lib/copland.rb +56 -0
  53. data/lib/copland/class-factory.rb +95 -0
  54. data/lib/copland/configuration-point.rb +38 -0
  55. data/lib/copland/configuration-point/common.rb +203 -0
  56. data/lib/copland/configuration-point/errors.rb +44 -0
  57. data/lib/copland/configuration-point/list.rb +59 -0
  58. data/lib/copland/configuration-point/map.rb +59 -0
  59. data/lib/copland/configuration/errors.rb +43 -0
  60. data/lib/copland/configuration/loader.rb +113 -0
  61. data/lib/copland/configuration/yaml/configuration-point.rb +87 -0
  62. data/lib/copland/configuration/yaml/implementor.rb +134 -0
  63. data/lib/copland/configuration/yaml/interceptor.rb +63 -0
  64. data/lib/copland/configuration/yaml/listener.rb +56 -0
  65. data/lib/copland/configuration/yaml/loader.rb +122 -0
  66. data/lib/copland/configuration/yaml/package.rb +125 -0
  67. data/lib/copland/configuration/yaml/parser.rb +71 -0
  68. data/lib/copland/configuration/yaml/schema.rb +165 -0
  69. data/lib/copland/configuration/yaml/service-point.rb +116 -0
  70. data/lib/copland/configuration/yaml/utils.rb +82 -0
  71. data/lib/copland/default-schema-processor.rb +144 -0
  72. data/lib/copland/errors.rb +82 -0
  73. data/lib/copland/event-producer.rb +95 -0
  74. data/lib/copland/impl/builder-factory.rb +112 -0
  75. data/lib/copland/impl/copland-config.yml +1 -0
  76. data/lib/copland/impl/include-exclude.rb +140 -0
  77. data/lib/copland/impl/logging-interceptor.rb +106 -0
  78. data/lib/copland/impl/package.yml +217 -0
  79. data/lib/copland/impl/startup.rb +116 -0
  80. data/lib/copland/impl/symbol-source-manager.rb +131 -0
  81. data/lib/copland/impl/symbol-source.rb +63 -0
  82. data/lib/copland/instantiator.rb +38 -0
  83. data/lib/copland/instantiator/abstract.rb +91 -0
  84. data/lib/copland/instantiator/complex.rb +96 -0
  85. data/lib/copland/instantiator/identity.rb +58 -0
  86. data/lib/copland/instantiator/simple.rb +68 -0
  87. data/lib/copland/interceptor-chain.rb +166 -0
  88. data/lib/copland/interceptor.rb +139 -0
  89. data/lib/copland/log-factory.rb +206 -0
  90. data/lib/copland/models.rb +39 -0
  91. data/lib/copland/models/abstract.rb +78 -0
  92. data/lib/copland/models/prototype-deferred.rb +58 -0
  93. data/lib/copland/models/prototype.rb +58 -0
  94. data/lib/copland/models/proxy.rb +100 -0
  95. data/lib/copland/models/singleton-deferred.rb +59 -0
  96. data/lib/copland/models/singleton.rb +77 -0
  97. data/lib/copland/models/threaded.rb +65 -0
  98. data/lib/copland/ordering.rb +123 -0
  99. data/lib/copland/package.rb +246 -0
  100. data/lib/copland/registry.rb +368 -0
  101. data/lib/copland/schema.rb +206 -0
  102. data/lib/copland/service-point.rb +282 -0
  103. data/lib/copland/utils.rb +221 -0
  104. data/lib/copland/version.rb +47 -0
  105. data/test/conf-test/list-bad-key.yml +30 -0
  106. data/test/conf-test/list-bad-missing.yml +28 -0
  107. data/test/conf-test/list-bad-type.yml +28 -0
  108. data/test/conf-test/list-good.yml +29 -0
  109. data/test/conf-test/map-bad-key.yml +25 -0
  110. data/test/conf-test/map-bad-missing.yml +24 -0
  111. data/test/conf-test/map-bad-type.yml +23 -0
  112. data/test/conf-test/map-good.yml +25 -0
  113. data/test/configuration-point/package.yml +52 -0
  114. data/test/configuration/yaml/config/copland-config.yml +2 -0
  115. data/test/configuration/yaml/config/module.yml +2 -0
  116. data/test/configuration/yaml/config/subdir/copland-config.yml +2 -0
  117. data/test/configuration/yaml/config/subdir/package.yml +4 -0
  118. data/test/configuration/yaml/defaults/package.yml +5 -0
  119. data/test/configuration/yaml/defaults/subdir/package.yml +4 -0
  120. data/test/configuration/yaml/tc_config-loader.rb +86 -0
  121. data/test/configuration/yaml/tc_configuration-point-processor.rb +134 -0
  122. data/test/configuration/yaml/tc_implementor-processor.rb +104 -0
  123. data/test/configuration/yaml/tc_interceptor-processor.rb +85 -0
  124. data/test/configuration/yaml/tc_listener-processor.rb +69 -0
  125. data/test/configuration/yaml/tc_loader.rb +74 -0
  126. data/test/configuration/yaml/tc_package-processor.rb +120 -0
  127. data/test/configuration/yaml/tc_parser.rb +94 -0
  128. data/test/configuration/yaml/tc_schema-parser.rb +160 -0
  129. data/test/configuration/yaml/tc_service-point-processor.rb +104 -0
  130. data/test/configuration/yaml/tc_type-validator.rb +90 -0
  131. data/test/custom-logger.yml +3 -0
  132. data/test/impl/logging/package.yml +44 -0
  133. data/test/impl/logging/services.rb +84 -0
  134. data/test/impl/startup/package.yml +46 -0
  135. data/test/impl/startup/services.rb +47 -0
  136. data/test/impl/symbols/package.yml +24 -0
  137. data/test/impl/symbols/services.rb +38 -0
  138. data/test/impl/tc_builder-factory.rb +173 -0
  139. data/test/impl/tc_logging-interceptor.rb +148 -0
  140. data/test/impl/tc_startup.rb +59 -0
  141. data/test/impl/tc_symbol-sources.rb +61 -0
  142. data/test/logger.yml +6 -0
  143. data/test/mock.rb +201 -0
  144. data/test/schema/bad-package.yml +65 -0
  145. data/test/schema/package.yml +102 -0
  146. data/test/schema/services.rb +5 -0
  147. data/test/services/package.yml +79 -0
  148. data/test/services/simple.rb +87 -0
  149. data/test/tc_class-factory.rb +93 -0
  150. data/test/tc_complex-instantiator.rb +107 -0
  151. data/test/tc_configuration-point-contrib.rb +74 -0
  152. data/test/tc_configuration-point-schema.rb +122 -0
  153. data/test/tc_configuration-point.rb +91 -0
  154. data/test/tc_default-schema-processor.rb +297 -0
  155. data/test/tc_identity-instantiator.rb +61 -0
  156. data/test/tc_interceptors.rb +84 -0
  157. data/test/tc_logger.rb +131 -0
  158. data/test/tc_models.rb +176 -0
  159. data/test/tc_package.rb +165 -0
  160. data/test/tc_proxy.rb +65 -0
  161. data/test/tc_registry.rb +141 -0
  162. data/test/tc_schema.rb +78 -0
  163. data/test/tc_service-point.rb +178 -0
  164. data/test/tc_service.rb +70 -0
  165. data/test/tc_simple-instantiator.rb +61 -0
  166. data/test/tests.rb +93 -0
  167. data/tutorial/01/main.rb +7 -0
  168. data/tutorial/01/package.yml +8 -0
  169. data/tutorial/01/tutorial.rb +7 -0
  170. data/tutorial/02/main.rb +10 -0
  171. data/tutorial/02/package.yml +27 -0
  172. data/tutorial/02/tutorial.rb +46 -0
  173. data/tutorial/03/main.rb +24 -0
  174. data/tutorial/03/package.yml +29 -0
  175. data/tutorial/03/tutorial.rb +48 -0
  176. data/tutorial/04/main.rb +24 -0
  177. data/tutorial/04/package.yml +35 -0
  178. data/tutorial/04/tutorial.rb +48 -0
  179. data/tutorial/05/functions/package.yml +16 -0
  180. data/tutorial/05/functions/services.rb +15 -0
  181. data/tutorial/05/main.rb +10 -0
  182. data/tutorial/05/package.yml +35 -0
  183. data/tutorial/05/tutorial.rb +53 -0
  184. metadata +260 -0
@@ -0,0 +1,49 @@
1
+ <html>
2
+ <head>
3
+ <title>Package Reference for Copland</title>
4
+ <link rel="stylesheet" type="text/css" href="packrat.css" />
5
+ </head>
6
+ <body>
7
+ <h1><a name="top"></a>Package Reference for Copland</h1>
8
+
9
+
10
+ <h2><a href="copland.html">copland</a></h2>
11
+
12
+
13
+ <div class="description">
14
+ The copland package is the standard package defined by the Copland distribution. It includes the core services and interceptors, such as the BuilderFactory and the LoggingInterceptor.
15
+ </div>
16
+
17
+
18
+ <h2><a href="copland.lib.html">copland.lib</a></h2>
19
+
20
+
21
+ <div class="description">
22
+ This package contains additional services, providing functionality beyond that given by the core set of services in Copland itself. These additional services include a multicast service factory, a synchronizing interceptor, and more.
23
+ </div>
24
+
25
+
26
+ <h2><a href="copland.remote.html">copland.remote</a></h2>
27
+
28
+
29
+ <div class="description">
30
+ The copland.remote package is where standard Copland services dealing with remote access to services or servers are kept.
31
+ </div>
32
+
33
+
34
+ <h2><a href="copland.webrick.html">copland.webrick</a></h2>
35
+
36
+
37
+ <div class="description">
38
+ Various Copland services related to dealing with WEBrick servers and servlets.
39
+ </div>
40
+
41
+
42
+ <div class="generated-by">
43
+ Generated by
44
+ <a href="http://copland.rubyforge.org">Copland</a>'s
45
+ Packrat documentation extractor
46
+ on Sun Sep 26 21:37:13 MDT 2004
47
+ </div>
48
+ </body>
49
+ </html>
@@ -0,0 +1,125 @@
1
+ body {
2
+ margin: 0px;
3
+ background: #FFF;
4
+ color: #000;
5
+ font-family: verdana, arial, sans-serif;
6
+ }
7
+
8
+ a[href] {
9
+ color: #00F;
10
+ text-decoration: none;
11
+ }
12
+
13
+ a[href]:hover {
14
+ text-decoration: underline;
15
+ }
16
+
17
+ h1 {
18
+ background: #007;
19
+ color: #FFF;
20
+ font-weight: bold;
21
+ border-bottom: 1px solid #000;
22
+ padding: 0.5em;
23
+ font-size: xx-large;
24
+ }
25
+
26
+ h2 {
27
+ background: #007;
28
+ color: #FFF;
29
+ font-weight: bold;
30
+ border-top: 1px solid #000;
31
+ border-bottom: 1px solid #000;
32
+ padding: 0.25em;
33
+ padding-left: 1em;
34
+ font-size: x-large;
35
+ }
36
+
37
+ h3 {
38
+ background: #FFA;
39
+ color: #000;
40
+ font-weight: bold;
41
+ border-top: 1px solid #000;
42
+ border-bottom: 1px solid #000;
43
+ padding: 0.25em;
44
+ padding-left: 1em;
45
+ font-size: large;
46
+ }
47
+
48
+ h4 {
49
+ background: #FFD;
50
+ color: #000;
51
+ font-weight: bold;
52
+ border: 1px solid #000;
53
+ padding: 0.25em;
54
+ padding-left: 1em;
55
+ font-size: normal;
56
+ }
57
+
58
+ h1 a[href], h2 a[href], h3 a[href] {
59
+ color: #FF0;
60
+ }
61
+
62
+ .item-body {
63
+ margin-left: 1em;
64
+ margin-right: 1em;
65
+ }
66
+
67
+ .description {
68
+ margin-left: 1em;
69
+ margin-right: 1em;
70
+ border: 1px dotted #777;
71
+ background: #FFE;
72
+ padding: 1em;
73
+ }
74
+
75
+ .definition-item {
76
+ margin-left: 2em;
77
+ }
78
+
79
+ .definition-item li {
80
+ margin-top: 0.25em;
81
+ }
82
+
83
+ .schema-item-title {
84
+ color: #000;
85
+ font-style: italic;
86
+ padding-left: 1em;
87
+ font-size: normal;
88
+ }
89
+
90
+ .schema-item {
91
+ padding: 0.5em;
92
+ margin-left: 1em;
93
+ border-left: 1px dashed #777;
94
+ }
95
+
96
+ .subschema-name {
97
+ font-weight: bold;
98
+ }
99
+
100
+ .subschema {
101
+ margin-left: 1em;
102
+ margin-top: 0.25em;
103
+ }
104
+
105
+ .subschema .description {
106
+ margin-right: 1em;
107
+ margin-left: 0em;
108
+ border: none;
109
+ background: #FFF;
110
+ padding: 0.5em;
111
+ }
112
+
113
+ .nav {
114
+ text-align: right;
115
+ font-style: italic;
116
+ margin: 2em;
117
+ }
118
+
119
+ .generated-by {
120
+ font-size: small;
121
+ font-style: italic;
122
+ margin-top: 2em;
123
+ padding: 1em;
124
+ border-top: 1px solid #000;
125
+ }
@@ -0,0 +1,47 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # * The names of its contributors may not be used to endorse or promote
17
+ # products derived from this software without specific prior written
18
+ # permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ # =============================================================================
32
+ #++
33
+
34
+ $:.unshift "../../lib"
35
+
36
+ require 'copland'
37
+
38
+ registry = Copland::Registry.build :log_device => STDOUT
39
+
40
+ calc = registry.service( "calc.Calculator" )
41
+
42
+ p calc.add( 5, 8 )
43
+ p calc.subtract( 5, 8 )
44
+ p calc.multiply( 5, 8 )
45
+ p calc.divide( 5, 8 )
46
+
47
+ registry.shutdown
@@ -0,0 +1,35 @@
1
+ ---
2
+ id: calc
3
+
4
+ configuration-points:
5
+
6
+ Operations:
7
+ type: map
8
+
9
+ contributions:
10
+
11
+ Operations:
12
+ :add: !!service Adder
13
+ :subtract: !!service Subtractor
14
+ :multiply: !!service Multiplier
15
+ :divide: !!service Divider
16
+
17
+ service-points:
18
+
19
+ Adder:
20
+ implementor: services/Adder
21
+
22
+ Subtractor:
23
+ implementor: services/Subtractor
24
+
25
+ Multiplier:
26
+ implementor: services/Multiplier
27
+
28
+ Divider:
29
+ implementor: services/Divider
30
+
31
+ Calculator:
32
+ implementor:
33
+ class: services/Calculator
34
+ parameters:
35
+ - !!configuration Operations
@@ -0,0 +1,74 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # * The names of its contributors may not be used to endorse or promote
17
+ # products derived from this software without specific prior written
18
+ # permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ # =============================================================================
32
+ #++
33
+
34
+ class Adder
35
+ def compute( a, b )
36
+ a.to_f + b.to_f
37
+ end
38
+ end
39
+
40
+ class Subtractor
41
+ def compute( a, b )
42
+ a.to_f - b.to_f
43
+ end
44
+ end
45
+
46
+ class Multiplier
47
+ def compute( a, b )
48
+ a.to_f * b.to_f
49
+ end
50
+ end
51
+
52
+ class Divider
53
+ def compute( a, b )
54
+ a.to_f / b.to_f
55
+ end
56
+ end
57
+
58
+ class Calculator
59
+ def initialize( operations )
60
+ @operations = operations
61
+ end
62
+
63
+ def method_missing( op, *args )
64
+ if @operations.has_key?( op )
65
+ @operations[ op ].compute( *args )
66
+ else
67
+ super
68
+ end
69
+ end
70
+
71
+ def respond_to?( op )
72
+ super || @operations.has_key?( op )
73
+ end
74
+ end
@@ -0,0 +1,11 @@
1
+ This example was originally submitted as a solution for the first Ruby Quiz
2
+ (http://www.grayproductions.net/ruby_quiz/). Although the scope of the
3
+ problem is really too small to adequately demonstrate IoC, it does show
4
+ a few features and is a good "bite-sized" example.
5
+
6
+ For a complete description of the problem this example solves, see:
7
+
8
+ http://www.grayproductions.net/ruby_quiz/quiz1.html
9
+
10
+ - Jamis Buck
11
+ 26 Sep 2004
@@ -0,0 +1,57 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ def can_require( file )
6
+ begin
7
+ require file
8
+ return true
9
+ rescue LoadError
10
+ return false
11
+ end
12
+ end
13
+
14
+ desc "Default task"
15
+ task :default => [ :demo ]
16
+
17
+ desc "Demonstration of the application"
18
+ task :demo do
19
+ puts "================================================================="
20
+ puts "This is a demonstration of Jamis Buck's solution to Ruby Quiz #1,"
21
+ puts "\"The Solitaire Cipher\". To run it yourself, invoke the script"
22
+ puts "\"bin/main.rb\", and pass the message(s) you want to encrypt or"
23
+ puts "decrypt as parameters."
24
+ puts "================================================================="
25
+ puts
26
+ sh 'ruby bin/main.rb "The rain in Spain stays mainly in the plain" ' +
27
+ '"CLEPK HHNIY CFPWH FDFEH"'
28
+ end
29
+
30
+ desc "Build documentation"
31
+ task :doc => [ :rdoc, :packrat ]
32
+
33
+ task :rdoc => Dir["lib/*.rb"]
34
+
35
+ desc "Clean generated files"
36
+ task :clean do
37
+ rm_rf "doc/api"
38
+ rm_rf "doc/packages"
39
+ end
40
+
41
+ desc "Generate the package reference documentation"
42
+ task :packrat => [ "doc/packages/index.html" ]
43
+
44
+ file "doc/packages/index.html" do
45
+ sh "packrat -o doc/packages -v -T 'Ruby Quiz #1: The Solitaire Cipher' lib"
46
+ end
47
+
48
+ Rake::TestTask.new do |t|
49
+ t.test_files = [ "test/tests.rb" ]
50
+ t.verbose = true
51
+ end
52
+
53
+ Rake::RDocTask.new do |rdoc|
54
+ rdoc.rdoc_dir = 'doc/api'
55
+ rdoc.title = "Ruby Quiz #1: The Solitaire Cipher"
56
+ rdoc.rdoc_files.include('lib/*.rb')
57
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join( File.dirname( __FILE__ ), "..", "..", "..", "lib" )
4
+ require 'copland'
5
+
6
+ libdir = File.join( File.dirname( __FILE__ ), "..", "lib" )
7
+ $: << libdir
8
+
9
+ registry = Copland::Registry.build libdir, :log_device => STDOUT
10
+
11
+ cli = registry.service( "solitaire.cipher.CLI" )
12
+ cli.run
13
+
14
+ registry.shutdown
@@ -0,0 +1,230 @@
1
+ require 'optparse'
2
+
3
+ class Deck
4
+
5
+ def initialize
6
+ @deck = (1..52).to_a + [ "A", "B" ]
7
+ @length = @deck.length
8
+ end
9
+
10
+ def cipher_shuffle!
11
+ # move joker A down one card, circularly
12
+ reposition_card( "A", 1 )
13
+
14
+ # move joker B down two cards, circularly
15
+ reposition_card( "B", 2 )
16
+
17
+ joker_A = @deck.index( "A" )
18
+ joker_B = @deck.index( "B" )
19
+
20
+ # move all cards above the top-most joker, below the bottom-most joker, and
21
+ # all cards below the bottom-most joker, above the top-most joker.
22
+ top = ( joker_A < joker_B ? joker_A : joker_B )
23
+ bottom = ( joker_A > joker_B ? joker_A : joker_B )
24
+ @deck = @deck[bottom+1..-1] + @deck[top..bottom] + @deck[0,top]
25
+
26
+ # take value of the bottom-most card, and cut that many cards off the
27
+ # top, inserting them just before the bottom-most card.
28
+ cut = @deck.last
29
+ @deck = @deck[cut..-2] + @deck[0,cut] + [ @deck.last ]
30
+ end
31
+
32
+ def cipher_letter
33
+ count = @deck.first
34
+ count = 53 if count.is_a?( String )
35
+ result = @deck[ count ]
36
+ return nil unless result.is_a? Fixnum
37
+ result -= 26 while result > 26
38
+ return (result+64).chr
39
+ end
40
+
41
+ def to_a
42
+ @deck.dup
43
+ end
44
+
45
+ def cards=( deck )
46
+ @deck = deck
47
+ @length = @deck.length
48
+ raise "the deck must contain an 'A' joker" unless @deck.include?("A")
49
+ raise "the deck must contain a 'B' joker" unless @deck.include?("B")
50
+ end
51
+
52
+ def reposition_card( card, delta )
53
+ pos = @deck.index card
54
+ @deck.delete_at pos
55
+ new_pos = pos + delta
56
+ new_pos = 1 + new_pos % @length if new_pos >= @length
57
+ @deck.insert new_pos, card
58
+ new_pos
59
+ end
60
+ private :reposition_card
61
+
62
+ end
63
+
64
+ class KeyingAlgorithms
65
+
66
+ attr_writer :algorithms
67
+ attr_writer :registry
68
+
69
+ def get( name )
70
+ svc_name = @algorithms[ name ]
71
+ raise "No such algorithm #{name.inspect}" if svc_name.nil?
72
+
73
+ return @registry.service( svc_name )
74
+ end
75
+
76
+ end
77
+
78
+ class UnkeyedAlgorithm
79
+
80
+ def new_deck
81
+ Deck.new
82
+ end
83
+
84
+ end
85
+
86
+ class KeyStream
87
+
88
+ attr_writer :deck
89
+
90
+ def next
91
+ loop do
92
+ @deck.cipher_shuffle!
93
+ letter = @deck.cipher_letter
94
+ return letter if letter
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ class SolitaireCipher
101
+
102
+ attr_writer :algorithms
103
+ attr_writer :stream
104
+
105
+ def initialize( default_algorithm )
106
+ @algorithm = default_algorithm
107
+ end
108
+
109
+ def use_algorithm( keying_algorithm )
110
+ @algorithm = @algorithms.get( keying_algorithm )
111
+ end
112
+
113
+ def encrypt( message )
114
+ reset
115
+
116
+ chars = message.split(//).map { |c| c.upcase }. reject { |c| c !~ /[A-Z]/ }
117
+ chars.concat ["X"] * ( 5 - chars.length % 5 ) if chars.length % 5 > 0
118
+ chars.map! { |c| c[0] - 64 }
119
+ key = generate_key( chars.length )
120
+ code = chars.zip( key ).map { |c,k| ( c + k > 26 ? c + k - 26 : c + k ) }.map { |c| (c+64).chr }
121
+
122
+ msg = ""
123
+ (code.length/5).times do
124
+ msg << " " if msg.length > 0
125
+ 5.times { msg << code.shift }
126
+ end
127
+
128
+ return msg
129
+ end
130
+
131
+ def decrypt( message )
132
+ raise "bad decrypt message: #{message.inspect}" if message =~ /[^A-Z ]/
133
+
134
+ reset
135
+ chars = message.split(//).reject { |c| c == " " }.map { |c| c[0] - 64 }
136
+ key = generate_key( chars.length )
137
+ chars.zip( key ).map { |c,k| ( k >= c ? c + 26 - k : c - k ) }.map { |c| (c+64).chr }.join
138
+ end
139
+
140
+ def generate_key( length )
141
+ key = []
142
+ length.times { key << @stream.next }
143
+ key.map { |c| c[0] - 64 }
144
+ end
145
+ private :generate_key
146
+
147
+ def reset
148
+ @stream.deck = @algorithm.new_deck
149
+ end
150
+ private :reset
151
+
152
+ end
153
+
154
+ class Options
155
+
156
+ attr_reader :strings
157
+ attr_reader :keying_algorithm
158
+
159
+ def initialize( argv = ARGV )
160
+ @named_options = Hash.new
161
+ @run_app = true
162
+ @keying_algorithm = "unkeyed"
163
+
164
+ OptionParser.new do |opts|
165
+ opts.banner = "Usage: #{$0} [options] [strings]"
166
+ opts.separator ""
167
+
168
+ opts.on( "-o", "--option NAME=VALUE",
169
+ "Specify a named value, for use by a component of the cipher."
170
+ ) do |pair|
171
+ name, value = pair.split( / *= */, 2 )
172
+ @named_options[ name ] = value
173
+ end
174
+
175
+ opts.on( "-k", "--key NAME", "Specify the keying algorithm to use" ) do |value|
176
+ @keying_algorithm = value
177
+ end
178
+
179
+ opts.separator ""
180
+
181
+ opts.on_tail( "-h", "--help", "This help text" ) do
182
+ puts opts
183
+ @run_app = false
184
+ end
185
+
186
+ opts.parse!( argv )
187
+ end
188
+
189
+ @strings = argv
190
+ end
191
+
192
+ def []( value )
193
+ @named_options[ value ]
194
+ end
195
+
196
+ def run_app?
197
+ @run_app
198
+ end
199
+
200
+ end
201
+
202
+
203
+ class BackwardsAlgorithm
204
+
205
+ def new_deck
206
+ deck = Deck.new
207
+ deck.cards = deck.to_a.reverse
208
+ deck
209
+ end
210
+
211
+ end
212
+
213
+ class ShuffleAlgorithm
214
+
215
+ attr_writer :options
216
+
217
+ def new_deck
218
+ deck = Deck.new
219
+ cards = deck.to_a
220
+
221
+ seed = ( @options[ "seed" ] || 0 ).to_i
222
+ srand seed
223
+
224
+ 7.times { cards.sort! { rand(3)-1 } }
225
+ deck.cards = cards
226
+
227
+ return deck
228
+ end
229
+
230
+ end