perquackey 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ == Git
2
+
3
+ == 0.8.0 -- 2011-12-23
4
+
5
+ * JSON api: GET /rstlne.json
6
+ * Use optparse-defaults for command line options.
7
+
1
8
  == 0.7.3 -- 2010-04-29
2
9
  * Document C extension.
3
10
 
@@ -1,18 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- begin
4
- require 'perquackey'
5
- rescue LoadError
6
- raise unless $!.message =~ /\bperquackey$/
7
-
8
- lib = File.expand_path('../../lib', __FILE__)
9
- if !$:.include?(lib)
10
- warn "WARN: #{$!}.\n Trying again with #{lib} on the $LOAD_PATH..."
11
- $:.unshift(lib)
12
- retry
13
- end
14
-
15
- raise
16
- end
17
-
3
+ require 'perquackey'
18
4
  Perquackey::Application.run!(ARGV)
@@ -1,31 +1,95 @@
1
- <form action="/" method="post">
2
- <input name="letters"
3
- value="<%= letters %>"
4
- autocomplete="on"
5
- autosave="perquackey"
6
- autofocus="on"
7
- maxlength="13"
8
- pattern="[a-z]{10}([a-z]{3})?"
9
- placeholder="Type your letters here."
10
- required="on"
11
- results="12"
12
- title="Perquackey rolls are 10 or 13 letters."
13
- type="search"
14
- />
15
- </form>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Perquackey</title>
6
+ <style>
7
+ body {
8
+ margin: 0 auto 5em;
9
+ width: 45em;
10
+ }
11
+ section {
12
+ margin-bottom: 1em;
13
+ }
14
+ table {
15
+ border-collapse: collapse;
16
+ }
17
+ tbody tr:nth-child(5) td {
18
+ border-bottom: 1px dashed #ccc;
19
+ }
20
+ td, th {
21
+ padding-right: 1em;
22
+ }
23
+ footer {
24
+ background-color: #eee;
25
+ padding: 1em;
26
+ }
27
+ </style>
28
+ </head>
16
29
 
17
- <table>
18
- <tr>
19
- <% words.headers.each do |header| %>
20
- <th><%= header %></th>
21
- <% end %>
22
- </tr>
30
+ <body>
31
+ <header>
32
+ <h1>Perquackey</h1>
33
+ </header>
23
34
 
24
- <% words.each do |row| %>
25
- <tr>
26
- <% row.each do |word| %>
27
- <td><%= word %></td>
28
- <% end %>
29
- </tr>
30
- <% end %>
31
- </table>
35
+ <section>
36
+ <form action="/" method="post">
37
+ <input name="letters"
38
+ autocomplete="off"
39
+ autofocus="on"
40
+ maxlength="13"
41
+ pattern="[a-z]{10}([a-z]{3})?"
42
+ placeholder="Enter your letters here."
43
+ required="on"
44
+ size="30"
45
+ title="Perquackey rolls are 10 or 13 letters."
46
+ value="<%= letters %>"
47
+ />
48
+ </form>
49
+ </section>
50
+
51
+ <section>
52
+ <table>
53
+ <thead>
54
+ <tr>
55
+ <% words.headers.each do |header| %>
56
+ <th><%= header %></th>
57
+ <% end %>
58
+ </tr>
59
+ </thead>
60
+
61
+ <tbody>
62
+ <% words.each do |row| %>
63
+ <tr>
64
+ <% row.each do |word| %>
65
+ <td><%= word %></td>
66
+ <% end %>
67
+ </tr>
68
+ <% end %>
69
+ </tbody>
70
+ </table>
71
+ </section>
72
+
73
+ <footer>
74
+ <p>
75
+ Enter the letters you rolled to see what you could have spelled.
76
+ </p>
77
+ <p>
78
+ Examples:
79
+ <a href="/eehhhijjoopqt">eehhhijjoopqt</a>,
80
+ <a href="/aaddeginoprsw">aaddeginoprsw</a>
81
+ </p>
82
+ <p>
83
+ These words are taken from
84
+ <a href="http://en.wikipedia.org/wiki/Tournament_Word_List">TWL06, the official word list</a>
85
+ for Scrabble tournaments in North America. (You can
86
+ <a href="http://www.isc.ro/en/commands/lists.html">download this list</a>
87
+ from the Internet Scrabble Club.)
88
+ </p>
89
+ <p>
90
+ <a href="https://github.com/matthewtodd/perquackey">This code is on GitHub</a>.
91
+ Patches welcome!
92
+ </p>
93
+ </footer>
94
+ </body>
95
+ </html>
@@ -1,5 +1,5 @@
1
1
  #include "ruby.h"
2
- #include "rubyio.h"
2
+ #include "ruby/io.h"
3
3
 
4
4
  #define MAX_LENGTH 40
5
5
  #define XOUT '@'
@@ -34,23 +34,6 @@ static int anagram_p(char *letters, char *word) {
34
34
  return TRUE;
35
35
  }
36
36
 
37
- /*
38
- * Document-class: Anagrams
39
- * Document-method: anagrams
40
- *
41
- * call-seq:
42
- * anagrams(letters) -> array
43
- *
44
- */
45
- static VALUE Anagrams_anagrams(VALUE self, VALUE letters) {
46
- return rb_apply(
47
- rb_apply(self,
48
- rb_intern("enum_for"),
49
- rb_ary_new3(2, rb_str_new2("each_anagram"), letters)),
50
- rb_intern("to_a"),
51
- rb_ary_new());
52
- }
53
-
54
37
  /*
55
38
  * Document-class: Anagrams
56
39
  * Document-method: each_anagram
@@ -62,11 +45,11 @@ static VALUE Anagrams_anagrams(VALUE self, VALUE letters) {
62
45
  static VALUE Anagrams_each_anagram(VALUE self, VALUE letters_value) {
63
46
  rb_io_t *stream;
64
47
  char word[MAX_LENGTH];
65
- char *letters = RSTRING(letters_value)->ptr;
48
+ char *letters = RSTRING_PTR(letters_value);
66
49
 
67
50
  GetOpenFile(self, stream);
68
51
 
69
- while (fgets(word, sizeof(word), stream->f) != NULL) {
52
+ while (fgets(word, sizeof(word), rb_io_stdio_file(stream)) != NULL) {
70
53
  chop(word);
71
54
 
72
55
  if (anagram_p(letters, word)) {
@@ -92,6 +75,5 @@ static VALUE Anagrams_each_anagram(VALUE self, VALUE letters_value) {
92
75
  void Init_anagrams() {
93
76
  mPerquackey = rb_define_module("Perquackey");
94
77
  mAnagrams = rb_define_module_under(mPerquackey, "Anagrams");
95
- rb_define_method(mAnagrams, "anagrams", Anagrams_anagrams, 1);
96
78
  rb_define_method(mAnagrams, "each_anagram", Anagrams_each_anagram, 1);
97
79
  }
@@ -1,26 +1,18 @@
1
+ require 'perquackey/version'
2
+
1
3
  require 'pathname'
2
- require 'rbconfig'
3
- require 'rbconfig/datadir'
4
+ require 'rubygems'
4
5
 
5
6
  module Perquackey
6
- VERSION = '0.7.3'
7
-
8
7
  autoload :Anagrams, 'perquackey/anagrams'
9
8
  autoload :Application,'perquackey/application'
10
9
  autoload :Console, 'perquackey/console'
11
10
  autoload :Dictionary, 'perquackey/dictionary'
12
11
  autoload :Game, 'perquackey/game'
13
12
  autoload :Server, 'perquackey/server'
14
- autoload :WordTable, 'perquackey/word_table'
13
+ autoload :Table, 'perquackey/table'
15
14
 
16
15
  def self.datadir
17
- @@datadir ||= begin
18
- datadir = RbConfig.datadir('perquackey')
19
- if !File.exist?(datadir)
20
- warn "WARN: #{datadir} does not exist.\n Trying again with relative data directory..."
21
- datadir = File.expand_path('../../data/perquackey', __FILE__)
22
- end
23
- Pathname.new(datadir)
24
- end
16
+ Pathname.new Gem.datadir('perquackey')
25
17
  end
26
18
  end
@@ -1,4 +1,4 @@
1
- require 'optparse'
1
+ require 'optparse/defaults'
2
2
 
3
3
  module Perquackey
4
4
  class Application
@@ -7,11 +7,10 @@ module Perquackey
7
7
  end
8
8
 
9
9
  def initialize
10
- @defaults = %w(--console)
11
-
12
- @options = OptionParser.new do |opts|
13
- opts.banner = "Usage: #{File.basename($0)} [-c|-s]"
14
- opts.version = Perquackey::VERSION
10
+ @options = OptionParser.with_defaults do |opts|
11
+ opts.banner = "Usage: #{File.basename($0)} [-c|-s]"
12
+ opts.defaults = %w(--console)
13
+ opts.version = Perquackey::VERSION
15
14
  opts.separator ''
16
15
 
17
16
  opts.on('-c', '--console', 'Run an interactive console.') do
@@ -22,19 +21,11 @@ module Perquackey
22
21
  @mode = :server
23
22
  @port = port || 3000
24
23
  end
25
-
26
- opts.separator ''
27
- opts.separator 'Defaults:'
28
- opts.separator "#{opts.summary_indent}#{@defaults.join(' ')}"
29
24
  end
30
25
  end
31
26
 
32
27
  def run!(argv)
33
- begin
34
- @options.parse(@defaults.dup.concat(argv))
35
- rescue OptionParser::ParseError
36
- @options.abort($!)
37
- end
28
+ @options.order(argv)
38
29
 
39
30
  case @mode
40
31
  when :console
@@ -6,37 +6,21 @@ module Perquackey
6
6
  new.run
7
7
  end
8
8
 
9
- def initialize
10
- @game = Game.new
11
- end
12
-
13
9
  def run
14
10
  puts 'Type ctrl-d or quit to exit.'
15
11
 
16
12
  loop do
17
- letters = prompt_for_letters
18
-
19
- case letters
13
+ case letters = Readline::readline('> ')
20
14
  when nil, 'quit'
21
15
  puts 'Goodbye.'
22
16
  exit
23
17
  when /^[a-z]+$/
24
18
  Readline::HISTORY.push(letters)
25
- puts words(letters)
19
+ puts Table.new(Dictionary.words(letters))
26
20
  else
27
21
  next
28
22
  end
29
23
  end
30
24
  end
31
-
32
- private
33
-
34
- def prompt_for_letters
35
- Readline::readline('> ')
36
- end
37
-
38
- def words(letters)
39
- @game.words(letters).map { |row| row.join(' ') }
40
- end
41
25
  end
42
26
  end
@@ -1,15 +1,21 @@
1
1
  module Perquackey
2
2
  class Dictionary
3
- TOURNAMENT_WORD_LIST = Perquackey.datadir.join('dict', 'TWL06.txt')
3
+ def self.words(letters)
4
+ new.words(letters)
5
+ end
4
6
 
5
7
  def initialize
6
- @word_list = TOURNAMENT_WORD_LIST
8
+ @word_list = Perquackey.datadir.join('dict', 'TWL06.txt')
7
9
  end
8
10
 
9
11
  def words(letters)
10
- @word_list.open do |stream|
11
- stream.extend(Anagrams).anagrams(letters)
12
+ anagrams = @word_list.open do |stream|
13
+ stream.extend(Anagrams)
14
+ stream.enum_for(:each_anagram, letters).to_a
12
15
  end
16
+
17
+ minimum = (letters.length <= 10) ? 3 : 4
18
+ anagrams.reject { |anagram| anagram.length < minimum }
13
19
  end
14
20
  end
15
21
  end
@@ -1,3 +1,4 @@
1
+ require 'json'
1
2
  require 'sinatra/base'
2
3
 
3
4
  module Perquackey
@@ -5,7 +6,15 @@ module Perquackey
5
6
  set :views, Perquackey.datadir.join('templates')
6
7
 
7
8
  get %r{^/([a-z]{0,13})$} do |letters|
8
- erb :index, :locals => { :letters => letters, :words => Game.new.words(letters) }
9
+ erb :index, :locals => {
10
+ :letters => letters,
11
+ :words => Table.new(Dictionary.words(letters))
12
+ }
13
+ end
14
+
15
+ get %r{^/([a-z]{0,13})\.json$} do |letters|
16
+ content_type :json
17
+ Dictionary.words(letters).to_json
9
18
  end
10
19
 
11
20
  post '/' do
@@ -1,5 +1,5 @@
1
1
  module Perquackey
2
- class WordTable
2
+ class Table
3
3
  include Enumerable
4
4
 
5
5
  def initialize(list=[])
@@ -27,5 +27,9 @@ module Perquackey
27
27
  yield headers.collect { |length| @table[length][row_number] or ' ' * length}
28
28
  end
29
29
  end
30
+
31
+ def to_s
32
+ map { |row| row.join(' ') }.join("\n")
33
+ end
30
34
  end
31
35
  end
@@ -0,0 +1,3 @@
1
+ module Perquackey
2
+ VERSION = '0.8.0'
3
+ end
@@ -1,7 +1,7 @@
1
- require 'test/helper'
1
+ require 'helper'
2
2
 
3
3
  class DictionaryTest < Test::Unit::TestCase
4
4
  def test_simple_search
5
- assert_equal ['ab', 'ba', 'cab'], Perquackey::Dictionary.new.words('abc')
5
+ assert_equal ['cab'], Perquackey::Dictionary.new.words('abc')
6
6
  end
7
7
  end
@@ -1,9 +1,2 @@
1
1
  require 'test/unit'
2
2
  require 'perquackey'
3
-
4
- begin
5
- require 'redgreen' if $stdout.tty?
6
- rescue LoadError
7
- # It's nice not to have hard dependencies on any gems for testing, so that
8
- # it's super-easy for your users to run `gem check --test perquackey.`
9
- end
@@ -0,0 +1,34 @@
1
+ require 'helper'
2
+
3
+ class TableTest < Test::Unit::TestCase
4
+ def test_handles_empty_list
5
+ empty_table = Perquackey::Table.new %w()
6
+
7
+ assert_equal [], empty_table.headers.to_a
8
+ assert_equal [], empty_table.to_a
9
+ end
10
+
11
+ def test_handles_some_list
12
+ table = Perquackey::Table.new %w(ape bear cat dog eagle fox goose hippo ibis)
13
+
14
+ assert_equal [3, 4, 5], table.headers.to_a
15
+
16
+ assert_equal [
17
+ ['ape', 'bear', 'eagle'],
18
+ ['cat', 'ibis', 'goose'],
19
+ ['dog', ' ', 'hippo'],
20
+ ['fox', ' ', ' ']
21
+ ], table.to_a
22
+ end
23
+
24
+ def test_to_s
25
+ table = Perquackey::Table.new %w(ape bear cat dog eagle fox goose hippo ibis)
26
+
27
+ assert_equal <<-END.gsub(/^ */, '').strip, table.to_s.strip
28
+ ape bear eagle
29
+ cat ibis goose
30
+ dog hippo
31
+ fox
32
+ END
33
+ end
34
+ end
metadata CHANGED
@@ -1,139 +1,137 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: perquackey
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 7
8
- - 3
9
- version: 0.7.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Matthew Todd
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2010-04-29 00:00:00 +03:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2011-12-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: &8436690 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.6.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *8436690
25
+ - !ruby/object:Gem::Dependency
21
26
  name: sinatra
27
+ requirement: &8436330 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
33
+ type: :runtime
22
34
  prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- version: "0"
35
+ version_requirements: *8436330
36
+ - !ruby/object:Gem::Dependency
37
+ name: optparse-defaults
38
+ requirement: &8435520 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.1.0
30
44
  type: :runtime
31
- version_requirements: *id001
32
- - !ruby/object:Gem::Dependency
33
- name: redgreen
34
45
  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
46
+ version_requirements: *8435520
47
+ - !ruby/object:Gem::Dependency
45
48
  name: ronn
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"
49
+ requirement: &8434880 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.5'
54
55
  type: :development
55
- version_requirements: *id003
56
- - !ruby/object:Gem::Dependency
57
- name: shoe
58
56
  prerelease: false
59
- requirement: &id004 !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- segments:
64
- - 0
65
- version: "0"
57
+ version_requirements: *8434880
58
+ - !ruby/object:Gem::Dependency
59
+ name: shoe
60
+ requirement: &8434180 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 0.8.0
66
66
  type: :development
67
- version_requirements: *id004
68
- description: Provides console session and simple webapp for looking up Perquackey word matches
67
+ prerelease: false
68
+ version_requirements: *8434180
69
+ description: Provides console session and simple webapp for looking up Perquackey
70
+ word matches
69
71
  email: matthew.todd@gmail.com
70
- executables:
72
+ executables:
71
73
  - perquackey
72
- extensions:
74
+ extensions:
73
75
  - ext/perquackey/extconf.rb
74
- extra_rdoc_files:
76
+ extra_rdoc_files:
75
77
  - CHANGELOG.rdoc
76
78
  - README.rdoc
77
79
  - TODO.rdoc
78
80
  - ext/perquackey/anagrams.c
79
- files:
81
+ files:
80
82
  - CHANGELOG.rdoc
81
83
  - README.rdoc
82
84
  - TODO.rdoc
83
85
  - bin/perquackey
84
86
  - data/perquackey/dict/TWL06.txt
85
87
  - data/perquackey/templates/index.erb
86
- - data/perquackey/templates/layout.erb
87
88
  - ext/perquackey/extconf.rb
88
89
  - ext/perquackey/anagrams.c
89
90
  - lib/perquackey/application.rb
90
91
  - lib/perquackey/console.rb
91
92
  - lib/perquackey/dictionary.rb
92
- - lib/perquackey/game.rb
93
93
  - lib/perquackey/server.rb
94
- - lib/perquackey/word_table.rb
94
+ - lib/perquackey/table.rb
95
+ - lib/perquackey/version.rb
95
96
  - lib/perquackey.rb
96
97
  - man/perquackey.1
97
98
  - man/perquackey.1.ronn
98
99
  - test/dictionary_test.rb
99
100
  - test/helper.rb
100
- - test/word_table_test.rb
101
- has_rdoc: true
101
+ - test/table_test.rb
102
102
  homepage: http://github.com/matthewtodd/perquackey
103
103
  licenses: []
104
-
105
104
  post_install_message:
106
- rdoc_options:
105
+ rdoc_options:
107
106
  - --main
108
107
  - README.rdoc
109
108
  - --title
110
- - perquackey-0.7.3
109
+ - perquackey-0.8.0
111
110
  - --inline-source
112
- require_paths:
111
+ require_paths:
113
112
  - lib
114
- required_ruby_version: !ruby/object:Gem::Requirement
115
- requirements:
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- segments:
119
- - 1
120
- - 8
121
- - 7
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
122
118
  version: 1.8.7
123
- required_rubygems_version: !ruby/object:Gem::Requirement
124
- requirements:
125
- - - ">="
126
- - !ruby/object:Gem::Version
127
- segments:
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ segments:
128
126
  - 0
129
- version: "0"
127
+ hash: -138864973
130
128
  requirements: []
131
-
132
129
  rubyforge_project:
133
- rubygems_version: 1.3.6
130
+ rubygems_version: 1.8.11
134
131
  signing_key:
135
132
  specification_version: 3
136
- summary: Provides console session and simple webapp for looking up Perquackey word matches
137
- test_files:
133
+ summary: Provides console session and simple webapp for looking up Perquackey word
134
+ matches
135
+ test_files:
138
136
  - test/dictionary_test.rb
139
- - test/word_table_test.rb
137
+ - test/table_test.rb
@@ -1,24 +0,0 @@
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>
@@ -1,17 +0,0 @@
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,23 +0,0 @@
1
- require 'test/helper'
2
-
3
- class WordTableTest < Test::Unit::TestCase
4
- def test_handles_empty_list
5
- empty_table = Perquackey::WordTable.new %w()
6
-
7
- assert_equal [], empty_table.headers.to_a
8
- assert_equal [], empty_table.to_a
9
- end
10
-
11
- def test_handles_some_list
12
- table = Perquackey::WordTable.new %w(ape bear cat dog eagle fox goose hippo ibis)
13
-
14
- assert_equal [3, 4, 5], table.headers.to_a
15
-
16
- assert_equal [
17
- 'ape bear eagle',
18
- 'cat ibis goose',
19
- 'dog hippo',
20
- 'fox '
21
- ], table.collect { |row| row.join(' ') }
22
- end
23
- end