perquackey 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ .rvmrc
2
+ Makefile
3
+ *.bundle
4
+ *.gem
5
+ *.o
6
+ rdoc
@@ -1,3 +1,11 @@
1
+ == Git
2
+ * Refactor Dictionary to have Ruby parts, with a C extension starting at the fgets on the IO stream.
3
+ * Reorganize code for autoloading.
4
+ * Reorganize code to properly use datadir.
5
+ * Begin scant documentation.
6
+ * Use HTML5 for web templates.
7
+ * Remove separate --port argument. It's now an optional part of --server.
8
+
1
9
  == 0.7.0 -- 2010-03-30
2
10
  * Switch from YAWL to TWL06 word list.
3
11
  * Upgrade build system to use Bundler.
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ gem 'perquackey', :path => File.expand_path('.')
4
+
5
+ group :development do
6
+ gem 'redgreen'
7
+ gem 'shoe', '0.5.0'
8
+ end
@@ -1,3 +1,53 @@
1
1
  = Perquackey
2
2
 
3
- The different word game.
3
+ Perquackey is "The different word game." I love it.
4
+
5
+ This tool helps you know what words you could have spelled, had you had more
6
+ time / vocabulary / clarity of thought. Sometimes it's helpful for learning,
7
+ and sometimes it's just annoying.
8
+
9
+ == Install
10
+
11
+ $ gem install perquackey
12
+
13
+ == Console Mode
14
+
15
+ $ perquackey
16
+ Type ctrl-d or quit to exit.
17
+ > foobar
18
+ abo barf
19
+ arb boar
20
+ arf boor
21
+ bar bora
22
+ boa broo
23
+ boo faro
24
+ bra fora
25
+ bro forb
26
+ fab roof
27
+ far
28
+ fob
29
+ for
30
+ fro
31
+ oaf
32
+ oar
33
+ oba
34
+ ora
35
+ orb
36
+ rob
37
+ > quit
38
+ Goodbye.
39
+ $
40
+
41
+ == Server Mode
42
+
43
+ $ perquackey --server
44
+ == Sinatra/1.0 has taken the stage on 3000 for development with backup from WEBrick
45
+ [2010-03-30 21:28:19] INFO WEBrick 1.3.1
46
+ [2010-03-30 21:28:19] INFO ruby 1.8.7 (2010-01-10) [i686-darwin10.2.0]
47
+ [2010-03-30 21:28:19] INFO WEBrick::HTTPServer#start: pid=37884 port=3000
48
+ ...
49
+
50
+ == Rack It Up
51
+
52
+ require 'perquackey'
53
+ run Perquackey::Server
data/Rakefile CHANGED
@@ -1,11 +1,3 @@
1
- require 'perquackey/version'
2
1
  require 'shoe'
3
2
 
4
- Shoe.tie('perquackey', Perquackey::VERSION, 'Provides console session and simple webapp for looking up Perquackey word matches') do |spec|
5
- spec.add_runtime_dependency('sinatra')
6
- end
7
-
8
- desc 'Run perquackey'
9
- task :exec, :options, :needs => :compile do |_, arguments|
10
- ruby "-rubygems -Iext -Ilib bin/perquackey #{arguments[:options]}"
11
- end
3
+ Shoe::Tasks.define('perquackey.gemspec')
data/TODO.rdoc CHANGED
@@ -1,6 +1,5 @@
1
1
  * Dictionary should take some kind of IO object.
2
2
  * Include the C extension in the rdoc.
3
- * Push a release to gemcutter.
4
3
  * Use the web interface for in-game support:
5
4
  * Capture words
6
5
  * Calculate score
@@ -1,31 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- #
3
- # To run this script in-project (rather than via rubygems wrapper), you'll
4
- # need to say something like:
5
- #
6
- # RUBYOPT=rubygems RUBYLIB=ext:lib ./bin/perquackey
7
- #
8
- require 'optparse'
9
- require 'ostruct'
10
2
 
11
- conf = OpenStruct.new(:mode => :console, :port => 3000)
12
-
13
- opts = OptionParser.new do |opts|
14
- opts.banner = "Usage: #{File.basename($0)} [options]"
15
- opts.separator ''
16
- opts.on('-s', '--server', 'Run as a web server') { conf.mode = :server }
17
- opts.on('-p', '--port PORT', "Port for web server (defaults to #{conf.port})") { |port| conf.port = port }
18
- opts.on('-h', '--help', 'Show this message') { puts opts; exit }
19
- opts.separator ''
20
- end
21
-
22
- opts.parse! ARGV
23
-
24
- case conf.mode
25
- when :console
26
- require 'perquackey/console'
27
- Perquackey::Console.run!
28
- when :server
29
- require 'perquackey/server'
30
- Perquackey::Server.run!(:port => conf.port)
31
- end
3
+ require 'perquackey'
4
+ Perquackey::Application.run!(ARGV)
@@ -0,0 +1,29 @@
1
+ <form action="/" method="post">
2
+ <input name="letters"
3
+ value="<%= letters %>"
4
+ autocomplete="on"
5
+ autofocus="on"
6
+ maxlength="13"
7
+ pattern="[a-z]{10}([a-z]{3})?"
8
+ placeholder="Type your letters here."
9
+ required="on"
10
+ title="Perquackey rolls are 10 or 13 letters."
11
+ type="search"
12
+ />
13
+ </form>
14
+
15
+ <table>
16
+ <tr>
17
+ <% words.headers.each do |header| %>
18
+ <th><%= header %></th>
19
+ <% end %>
20
+ </tr>
21
+
22
+ <% words.each do |row| %>
23
+ <tr>
24
+ <% row.each do |word| %>
25
+ <td><%= word %></td>
26
+ <% end %>
27
+ </tr>
28
+ <% end %>
29
+ </table>
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Perquackey</title>
6
+ </head>
7
+
8
+ <body>
9
+ <header>
10
+ <h1>Perquackey</h1>
11
+ </header>
12
+
13
+ <%= yield %>
14
+
15
+ <footer>
16
+ <p>
17
+ Now using the
18
+ <a href="http://en.wikipedia.org/wiki/Tournament_Word_List">TWL06 word list</a>
19
+ courtesy of the
20
+ <a href="http://www.isc.ro/en/commands/lists.html">Internet Scrabble Club</a>.
21
+ </p>
22
+ </footer>
23
+ </body>
24
+ </html>
@@ -0,0 +1,69 @@
1
+ #include "ruby.h"
2
+ #include "rubyio.h"
3
+
4
+ #define MAX_LENGTH 40
5
+ #define XOUT '@'
6
+ #define FALSE 0
7
+ #define TRUE 1
8
+
9
+ static VALUE mPerquackey;
10
+ static VALUE mAnagrams;
11
+
12
+ void chop(char *string) {
13
+ int length = strlen(string);
14
+
15
+ if (length > 0 && string[length-1] == '\n') {
16
+ string[length-1] = '\0';
17
+ }
18
+ }
19
+
20
+ int anagram_p(char *letters, char *word) {
21
+ static char scratch_pad[MAX_LENGTH];
22
+ register char *scratch_pad_ptr;
23
+
24
+ strcpy(scratch_pad, letters);
25
+
26
+ while (*word) {
27
+ if ((scratch_pad_ptr = strchr(scratch_pad, *word++)) != NULL) {
28
+ *scratch_pad_ptr = XOUT;
29
+ } else {
30
+ return FALSE;
31
+ }
32
+ }
33
+
34
+ return TRUE;
35
+ }
36
+
37
+ VALUE Anagrams_anagrams(VALUE self, VALUE letters) {
38
+ return rb_apply(
39
+ rb_apply(self,
40
+ rb_intern("enum_for"),
41
+ rb_ary_new3(2, rb_str_new2("each_anagram"), letters)),
42
+ rb_intern("to_a"),
43
+ rb_ary_new());
44
+ }
45
+
46
+ VALUE Anagrams_each_anagram(VALUE self, VALUE letters_value) {
47
+ rb_io_t *stream;
48
+ char word[MAX_LENGTH];
49
+ char *letters = RSTRING(letters_value)->ptr;
50
+
51
+ GetOpenFile(self, stream);
52
+
53
+ while (fgets(word, sizeof(word), stream->f) != NULL) {
54
+ chop(word);
55
+
56
+ if (anagram_p(letters, word)) {
57
+ rb_yield(rb_str_new2(word));
58
+ }
59
+ }
60
+
61
+ return Qnil;
62
+ }
63
+
64
+ void Init_anagrams() {
65
+ mPerquackey = rb_define_module("Perquackey");
66
+ mAnagrams = rb_define_module_under(mPerquackey, "Anagrams");
67
+ rb_define_method(mAnagrams, "anagrams", Anagrams_anagrams, 1);
68
+ rb_define_method(mAnagrams, "each_anagram", Anagrams_each_anagram, 1);
69
+ }
@@ -1,2 +1,2 @@
1
1
  require 'mkmf'
2
- create_makefile 'perquackey/dictionary'
2
+ create_makefile 'perquackey/anagrams'
@@ -1,51 +1,19 @@
1
- require 'perquackey/dictionary'
1
+ require 'pathname'
2
+ require 'rbconfig'
3
+ require 'rbconfig/datadir'
2
4
 
3
5
  module Perquackey
4
- class Game
5
- TWL = File.expand_path('../perquackey/resources/TWL06.txt', __FILE__)
6
-
7
- def initialize
8
- @dictionary = Dictionary.new(TWL)
9
- end
10
-
11
- def words(letters)
12
- WordTable.new(@dictionary.words(letters).reject { |word| word.length < minimum_length(letters) })
13
- end
14
-
15
- private
16
-
17
- def minimum_length(letters)
18
- letters.length > 10 ? 4 : 3
19
- end
20
- end
21
-
22
- class WordTable
23
- include Enumerable
24
-
25
- def initialize(list=[])
26
- @table = Hash.new { |h, k| h[k] = [] }
27
-
28
- list.each do |word|
29
- @table[word.length] << word
30
- end
31
-
32
- if @table.empty?
33
- @headers = []
34
- @height = 0
35
- else
36
- @headers = @table.keys.min .. @table.keys.max
37
- @height = @table.values.max { |a, b| a.length <=> b.length }.length
38
- end
39
- end
40
-
41
- def headers
42
- @headers
43
- end
44
-
45
- def each
46
- @height.times do |row_number|
47
- yield headers.collect { |length| @table[length][row_number] or ' ' * length}
48
- end
49
- end
6
+ VERSION = '0.7.1'
7
+
8
+ autoload :Anagrams, 'perquackey/anagrams'
9
+ autoload :Application,'perquackey/application'
10
+ autoload :Console, 'perquackey/console'
11
+ autoload :Dictionary, 'perquackey/dictionary'
12
+ autoload :Game, 'perquackey/game'
13
+ autoload :Server, 'perquackey/server'
14
+ autoload :WordTable, 'perquackey/word_table'
15
+
16
+ def self.datadir
17
+ Pathname.new RbConfig.datadir('perquackey')
50
18
  end
51
19
  end
@@ -0,0 +1,48 @@
1
+ require 'optparse'
2
+
3
+ module Perquackey
4
+ class Application
5
+ def self.run!(argv) #:nodoc:
6
+ new.run!(argv)
7
+ end
8
+
9
+ def initialize
10
+ @mode = :console
11
+
12
+ @options = OptionParser.new do |opts|
13
+ opts.banner = "Usage: #{File.basename($0)} [OPTIONS]"
14
+ opts.separator ''
15
+ opts.separator 'Specific options:'
16
+
17
+ opts.on('-s', '--server [PORT]', 'Run a web server.') do |port|
18
+ @mode = :server
19
+ @port = port || 3000
20
+ end
21
+
22
+ opts.separator ''
23
+ opts.separator 'Common options:'
24
+
25
+ opts.on_tail('-h', '--help', 'Show this message.') do
26
+ puts opts
27
+ exit
28
+ end
29
+
30
+ opts.on_tail('-v', '--version', 'Print version and exit.') do
31
+ puts "perquackey #{Perquackey::VERSION}"
32
+ exit
33
+ end
34
+ end
35
+ end
36
+
37
+ def run!(argv)
38
+ @options.parse!(argv)
39
+
40
+ case @mode
41
+ when :console
42
+ Perquackey::Console.run!
43
+ when :server
44
+ Perquackey::Server.run!(:port => @port)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,4 +1,3 @@
1
- require 'perquackey'
2
1
  require 'readline'
3
2
 
4
3
  module Perquackey
@@ -8,7 +7,7 @@ module Perquackey
8
7
  end
9
8
 
10
9
  def initialize
11
- @game = Perquackey::Game.new
10
+ @game = Game.new
12
11
  end
13
12
 
14
13
  def run
@@ -0,0 +1,15 @@
1
+ module Perquackey
2
+ class Dictionary
3
+ TOURNAMENT_WORD_LIST = Perquackey.datadir.join('dict', 'TWL06.txt')
4
+
5
+ def initialize
6
+ @word_list = TOURNAMENT_WORD_LIST
7
+ end
8
+
9
+ def words(letters)
10
+ @word_list.open do |stream|
11
+ stream.extend(Anagrams).anagrams(letters)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Perquackey
2
+ class Game
3
+ def initialize
4
+ @dictionary = Dictionary.new
5
+ end
6
+
7
+ def words(letters)
8
+ WordTable.new(@dictionary.words(letters).reject { |word| word.length < minimum_length(letters) })
9
+ end
10
+
11
+ private
12
+
13
+ def minimum_length(letters)
14
+ letters.length > 10 ? 4 : 3
15
+ end
16
+ end
17
+ end
@@ -1,9 +1,8 @@
1
- require 'perquackey'
2
1
  require 'sinatra/base'
3
2
 
4
3
  module Perquackey
5
4
  class Server < Sinatra::Base
6
- set :views, File.dirname(__FILE__) + '/server'
5
+ set :views, Perquackey.datadir.join('templates')
7
6
 
8
7
  get %r{^/([a-z]{0,13})$} do |letters|
9
8
  erb :index, :locals => { :letters => letters, :words => Game.new.words(letters) }
@@ -0,0 +1,31 @@
1
+ module Perquackey
2
+ class WordTable
3
+ include Enumerable
4
+
5
+ def initialize(list=[])
6
+ @table = Hash.new { |h, k| h[k] = [] }
7
+
8
+ list.each do |word|
9
+ @table[word.length] << word
10
+ end
11
+
12
+ if @table.empty?
13
+ @headers = []
14
+ @height = 0
15
+ else
16
+ @headers = @table.keys.min .. @table.keys.max
17
+ @height = @table.values.max { |a, b| a.length <=> b.length }.length
18
+ end
19
+ end
20
+
21
+ def headers
22
+ @headers
23
+ end
24
+
25
+ def each
26
+ @height.times do |row_number|
27
+ yield headers.collect { |length| @table[length][row_number] or ' ' * length}
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,33 +1,33 @@
1
- # -*- encoding: utf-8 -*-
1
+ $:.unshift File.expand_path('../lib', __FILE__)
2
+ require 'perquackey'
2
3
 
3
- Gem::Specification.new do |s|
4
- s.name = %q{perquackey}
5
- s.version = "0.7.0"
4
+ Gem::Specification.new do |spec|
5
+ spec.name = 'perquackey'
6
+ spec.version = Perquackey::VERSION
6
7
 
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Matthew Todd"]
9
- s.date = %q{2010-03-30}
10
- s.default_executable = %q{perquackey}
11
- s.email = %q{matthew.todd@gmail.com}
12
- s.executables = ["perquackey"]
13
- s.extensions = ["ext/perquackey/extconf.rb"]
14
- s.extra_rdoc_files = ["CHANGELOG.rdoc", "README.rdoc", "TODO.rdoc"]
15
- s.files = ["Rakefile", "lib/perquackey", "lib/perquackey/console.rb", "lib/perquackey/dictionary.bundle", "lib/perquackey/resources", "lib/perquackey/resources/TWL06.txt", "lib/perquackey/server", "lib/perquackey/server/index.erb", "lib/perquackey/server/layout.erb", "lib/perquackey/server.rb", "lib/perquackey/version.rb", "lib/perquackey.rb", "bin/perquackey", "CHANGELOG.rdoc", "README.rdoc", "TODO.rdoc", "perquackey.gemspec", "test/dictionary_test.rb", "test/test_helper.rb", "test/word_table_test.rb", "ext/perquackey/extconf.rb", "ext/perquackey/dictionary.c"]
16
- s.rdoc_options = ["--main", "README.rdoc", "--title", "perquackey-0.7.0", "--inline-source"]
17
- s.require_paths = ["lib"]
18
- s.rubygems_version = %q{1.3.6}
19
- s.summary = %q{Provides console session and simple webapp for looking up Perquackey word matches}
8
+ spec.summary = 'Provides console session and simple webapp for looking up Perquackey word matches'
9
+ spec.description = spec.summary
10
+ spec.author = 'Matthew Todd'
11
+ spec.email = 'matthew.todd@gmail.com'
12
+ spec.homepage = 'http://github.com/matthewtodd/perquackey'
20
13
 
21
- if s.respond_to? :specification_version then
22
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
- s.specification_version = 3
14
+ spec.add_runtime_dependency 'sinatra'
15
+ spec.add_development_dependency 'redgreen'
16
+ spec.add_development_dependency 'shoe'
24
17
 
25
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
- s.add_runtime_dependency(%q<sinatra>, [">= 0"])
27
- else
28
- s.add_dependency(%q<sinatra>, [">= 0"])
29
- end
30
- else
31
- s.add_dependency(%q<sinatra>, [">= 0"])
18
+ def spec.git_files(glob=nil)
19
+ `git ls-files -z --cached --other --exclude-standard #{glob}`.split("\0")
32
20
  end
21
+
22
+ spec.files = spec.git_files
23
+ spec.executables = spec.git_files('bin/*').map &File.method(:basename)
24
+ spec.extensions = spec.git_files('ext/**/extconf.rb')
25
+ spec.test_files = spec.git_files('test/{,**/}*_test.rb')
26
+
27
+ spec.extra_rdoc_files = spec.git_files('{,**/}*.rdoc')
28
+ spec.rdoc_options = %W(
29
+ --main README.rdoc
30
+ --title #{spec.full_name}
31
+ --inline-source
32
+ )
33
33
  end
@@ -1,7 +1,7 @@
1
- require 'test_helper'
1
+ require 'test/helper'
2
2
 
3
3
  class DictionaryTest < Test::Unit::TestCase
4
- def test_simple_search_with_twl
5
- assert_equal ['ab', 'ba', 'cab'], Perquackey::Dictionary.new(Perquackey::Game::TWL).words('abc')
4
+ def test_simple_search
5
+ assert_equal ['ab', 'ba', 'cab'], Perquackey::Dictionary.new.words('abc')
6
6
  end
7
7
  end
@@ -1,7 +1,6 @@
1
1
  require 'perquackey'
2
2
  require 'test/unit'
3
3
 
4
- if $stdin.tty?
5
- require 'rubygems'
4
+ if $stdout.tty?
6
5
  require 'redgreen'
7
6
  end
@@ -1,17 +1,23 @@
1
- require 'test_helper'
1
+ require 'test/helper'
2
2
 
3
3
  class WordTableTest < Test::Unit::TestCase
4
4
  def test_handles_empty_list
5
- empty_table = Perquackey::WordTable.new []
5
+ empty_table = Perquackey::WordTable.new %w()
6
6
 
7
7
  assert_equal [], empty_table.headers.to_a
8
- assert_equal [], empty_table.collect { |row| row }
8
+ assert_equal [], empty_table.to_a
9
9
  end
10
10
 
11
11
  def test_handles_some_list
12
- table = Perquackey::WordTable.new %w[ape bear cat dog eagle fox goose hippo ibis]
12
+ table = Perquackey::WordTable.new %w(ape bear cat dog eagle fox goose hippo ibis)
13
13
 
14
14
  assert_equal [3, 4, 5], table.headers.to_a
15
- assert_equal ['ape bear eagle', 'cat ibis goose', 'dog hippo', 'fox '], table.collect { |row| row.join(' ') }
15
+
16
+ assert_equal [
17
+ 'ape bear eagle',
18
+ 'cat ibis goose',
19
+ 'dog hippo',
20
+ 'fox '
21
+ ], table.collect { |row| row.join(' ') }
16
22
  end
17
- end
23
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 7
8
- - 0
9
- version: 0.7.0
8
+ - 1
9
+ version: 0.7.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Matthew Todd
@@ -14,8 +14,8 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-30 00:00:00 +03:00
18
- default_executable: perquackey
17
+ date: 2010-04-16 00:00:00 +03:00
18
+ default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: sinatra
@@ -29,7 +29,31 @@ dependencies:
29
29
  version: "0"
30
30
  type: :runtime
31
31
  version_requirements: *id001
32
- description:
32
+ - !ruby/object:Gem::Dependency
33
+ name: redgreen
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ type: :development
43
+ version_requirements: *id002
44
+ - !ruby/object:Gem::Dependency
45
+ name: shoe
46
+ prerelease: false
47
+ requirement: &id003 !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ type: :development
55
+ version_requirements: *id003
56
+ description: Provides console session and simple webapp for looking up Perquackey word matches
33
57
  email: matthew.todd@gmail.com
34
58
  executables:
35
59
  - perquackey
@@ -40,27 +64,31 @@ extra_rdoc_files:
40
64
  - README.rdoc
41
65
  - TODO.rdoc
42
66
  files:
43
- - Rakefile
44
- - lib/perquackey/console.rb
45
- - lib/perquackey/dictionary.bundle
46
- - lib/perquackey/resources/TWL06.txt
47
- - lib/perquackey/server/index.erb
48
- - lib/perquackey/server/layout.erb
49
- - lib/perquackey/server.rb
50
- - lib/perquackey/version.rb
51
- - lib/perquackey.rb
52
- - bin/perquackey
67
+ - .gitignore
53
68
  - CHANGELOG.rdoc
69
+ - Gemfile
54
70
  - README.rdoc
71
+ - Rakefile
55
72
  - TODO.rdoc
73
+ - bin/perquackey
74
+ - data/perquackey/dict/TWL06.txt
75
+ - data/perquackey/templates/index.erb
76
+ - data/perquackey/templates/layout.erb
77
+ - ext/perquackey/anagrams.c
78
+ - ext/perquackey/extconf.rb
79
+ - lib/perquackey.rb
80
+ - lib/perquackey/application.rb
81
+ - lib/perquackey/console.rb
82
+ - lib/perquackey/dictionary.rb
83
+ - lib/perquackey/game.rb
84
+ - lib/perquackey/server.rb
85
+ - lib/perquackey/word_table.rb
56
86
  - perquackey.gemspec
57
87
  - test/dictionary_test.rb
58
- - test/test_helper.rb
88
+ - test/helper.rb
59
89
  - test/word_table_test.rb
60
- - ext/perquackey/extconf.rb
61
- - ext/perquackey/dictionary.c
62
90
  has_rdoc: true
63
- homepage:
91
+ homepage: http://github.com/matthewtodd/perquackey
64
92
  licenses: []
65
93
 
66
94
  post_install_message:
@@ -68,7 +96,7 @@ rdoc_options:
68
96
  - --main
69
97
  - README.rdoc
70
98
  - --title
71
- - perquackey-0.7.0
99
+ - perquackey-0.7.1
72
100
  - --inline-source
73
101
  require_paths:
74
102
  - lib
@@ -93,5 +121,6 @@ rubygems_version: 1.3.6
93
121
  signing_key:
94
122
  specification_version: 3
95
123
  summary: Provides console session and simple webapp for looking up Perquackey word matches
96
- test_files: []
97
-
124
+ test_files:
125
+ - test/dictionary_test.rb
126
+ - test/word_table_test.rb
@@ -1,68 +0,0 @@
1
- // After finding YAWL, I pretty much lifted this algorithm straight from its
2
- // anagram.c. It's certainly much faster than the Ruby code I wrote, since
3
- // it's not making tons of throwaway strings. Fun stuff.
4
- #include "ruby.h"
5
-
6
- #define MAX_LENGTH 40
7
- #define XOUT '@'
8
- #define FALSE 0
9
- #define TRUE 1
10
-
11
- static VALUE mPerquackey;
12
- static VALUE cDictionary;
13
-
14
- int spell(char *word, char *letters) {
15
- static char letter_set[MAX_LENGTH];
16
- register char *letter;
17
-
18
- strcpy(letter_set, letters);
19
- strcat(letter_set, "\n");
20
-
21
- while (*word) {
22
- if ((letter = strchr(letter_set, *word++)) != NULL) {
23
- *letter = XOUT;
24
- } else {
25
- return FALSE;
26
- }
27
- }
28
-
29
- return TRUE;
30
- }
31
-
32
- // It's very tempting to move Dictionary#initialize into Ruby-land, but part
33
- // of me thinks that it's cognitively easier to deal with if all of the
34
- // Dictionary code to be in one file instead of 2. (And this constructor's not
35
- // all that hard to read / write.)
36
- VALUE Dictionary_initialize(VALUE self, VALUE filename) {
37
- rb_iv_set(self, "@filename", filename);
38
- return self;
39
- }
40
-
41
- // It's tempting to move Dictionary#words method into Ruby-land, just
42
- // delegating to C for the time-critical work done by spell (i.e.
43
- // File.readlines(@filename).select { |word| spell(word, letters) }), but
44
- // there's a second, subtler benefit to keeping things here: that we don't
45
- // have to build a Ruby string ('word') for each line in @filename -- fgets is
46
- // wicked fast!
47
- VALUE Dictionary_words(VALUE self, VALUE letters) {
48
- VALUE words = rb_ary_new();
49
-
50
- char word[MAX_LENGTH];
51
-
52
- FILE *file = fopen(RSTRING(rb_iv_get(self, "@filename"))->ptr, "rt");
53
- while (fgets(word, MAX_LENGTH, file) != NULL) {
54
- if (spell(word, RSTRING(letters)->ptr)) {
55
- rb_ary_push(words, rb_str_new(word, strlen(word) - 1)); // strlen(word) - 1 to strip the trailing newline
56
- }
57
- }
58
- fclose(file);
59
-
60
- return words;
61
- }
62
-
63
- void Init_dictionary() {
64
- mPerquackey = rb_define_module("Perquackey");
65
- cDictionary = rb_define_class_under(mPerquackey, "Dictionary", rb_cObject);
66
- rb_define_method(cDictionary, "initialize", Dictionary_initialize, 1);
67
- rb_define_method(cDictionary, "words", Dictionary_words, 1);
68
- }
@@ -1,23 +0,0 @@
1
- <form name="form" action="/" method="post">
2
- <input name="letters" value="<%= letters %>" autocomplete="off">
3
- </form>
4
-
5
- <script type="text/javascript">
6
- document.forms.form.letters.focus();
7
- </script>
8
-
9
- <table>
10
- <tr>
11
- <% words.headers.each do |header| %>
12
- <th><%= header %></th>
13
- <% end %>
14
- </tr>
15
-
16
- <% words.each do |row| %>
17
- <tr>
18
- <% row.each do |word| %>
19
- <td><%= word %></td>
20
- <% end %>
21
- </tr>
22
- <% end %>
23
- </table>
@@ -1,12 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8" ?>
2
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
- <html lang="en-US" xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
4
- <head>
5
- <title>Perquackey</title>
6
- </head>
7
- <body>
8
- <h1>Perquackey</h1>
9
- <%= yield %>
10
- <p>Now using the <a href="http://en.wikipedia.org/wiki/Tournament_Word_List">TWL06 word list</a> courtesy of the <a href="http://www.isc.ro/en/commands/lists.html">Internet Scrabble Club</a>.</p>
11
- </body>
12
- </html>
@@ -1,3 +0,0 @@
1
- module Perquackey
2
- VERSION = '0.7.0'
3
- end