copland 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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