diff --git a/.gitignore b/.gitignore
index d20dc54..652257d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,10 @@
/test/version_tmp/
/tmp/
.DS_Store
+*.bundle
+*.o
+ext/rucaptcha/Makefile
+ext/rucaptcha/*.gif
## RubyMine Ide files
.idea/
diff --git a/.travis.yml b/.travis.yml
index bbdbe04..f3fd9b7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,8 +3,5 @@ rvm:
- 2.2.3
services:
- memcached
-addons:
- apt:
- packages:
- - imagemagick
- - tesseract-ocr
+script:
+ - bundle exec rake compile && bundle exec rake
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3f24c48..3fe0346 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+2.0.0
+-----
+
+*Break Changes!*
+
+WARNING!: This version have so many break changes!
+
+- Use C ext instead of ImageMagick, now it's no dependencies!
+- New captcha style.
+- Remove `len`, `font_size`, `cache_limit` config key, no support now.
+- Output `GIF` format.
+
1.2.0
-----
diff --git a/Gemfile.lock b/Gemfile.lock
index cd11400..80834f9 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- rucaptcha (1.2.0)
+ rucaptcha (2.0.0)
railties (>= 3.2)
GEM
@@ -96,6 +96,8 @@ GEM
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (11.3.0)
+ rake-compiler (1.0.3)
+ rake
rspec (3.3.0)
rspec-core (~> 3.3.0)
rspec-expectations (~> 3.3.0)
@@ -135,8 +137,9 @@ DEPENDENCIES
dalli
rails
rake
+ rake-compiler (~> 1)
rspec
rucaptcha!
BUNDLED WITH
- 1.13.6
+ 1.13.7
diff --git a/README.md b/README.md
index 4dae17e..4446682 100644
--- a/README.md
+++ b/README.md
@@ -4,44 +4,20 @@
[](https://travis-ci.org/huacnlee/rucaptcha)
[](https://codeclimate.com/github/huacnlee/rucaptcha)
-This is a Captcha gem for Rails Applications. It runs an ImageMagick command to draw Captcha image - so it has NO performance issues or memory leak issues. **There is NO: RMagick**
+This is a Captcha gem for Rails Applications. It drawing captcha image with C code.
## Example
-
-
-
-
-
-
-
-
-Idea by: https://ruby-china.org/topics/20558#reply4
+
[中文介绍和使用说明](https://ruby-china.org/topics/27832)
## Feature
-- Only need `ImageMagick`, No `RMagick`, No `mini_magick`;
+- No dependencies. No ImageMagick, No RMagick.
- For Rails Application;
- Simple, Easy to use;
-- File Caching for performance.
-
-## Requirements
-
-- ImageMagick 6.9+
-
-#### Ubuntu
-
-```
-sudo apt-get install imagemagick ghostscript
-```
-
-#### Mac OS X
-
-```bash
-brew install imagemagick ghostscript
-```
+- High performance.
## Usage
@@ -55,17 +31,10 @@ Create `config/initializers/rucaptcha.rb`
```rb
RuCaptcha.configure do
- # Number of chars, default: 4
- self.len = 4
- # Image font size, default: 45
- self.font_size = 45
- # Cache generated images in file store, this is config files limit, default: 100
- # set 0 to disable file cache.
- self.cache_limit = 100
- # Custom captcha code expire time if you need, default: 2 minutes
- # self.expires_in = 120
# Color style, default: :colorful, allows: [:colorful, :black_white]
# self.style = :colorful
+ # Custom captcha code expire time if you need, default: 2 minutes
+ # self.expires_in = 120
# [Requirement]
# Store Captcha code where, this config more like Rails config.cache_store
# default: Rails application config.cache_store
@@ -99,7 +68,7 @@ class AccountController < ApplicationController
end
```
-> TIP: Sometime you may need keep last verified captcha code in session on `verify_rucaptcha?` method call, you can use `keep_session: true`. For example: ` Verify_rucaptcha? (@user, keep_session: true) `.
+> TIP: Sometime you may need keep last verified captcha code in session on `verify_rucaptcha?` method call, you can use `keep_session: true`. For example: `verify_rucaptcha? @user, keep_session: true`.
View `app/views/account/new.html.erb`
diff --git a/Rakefile b/Rakefile
index 378dab3..3c74416 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,5 +1,18 @@
require "bundler/gem_tasks"
require "rspec/core/rake_task"
+require 'rake/extensiontask'
+
+Rake::ExtensionTask.new "rucaptcha" do |ext|
+ ext.lib_dir = "lib/rucaptcha"
+end
RSpec::Core::RakeTask.new(:spec)
task default: :spec
+
+
+task :preview do
+ require 'rucaptcha'
+
+ res = RuCaptcha.create(1)
+ puts res[1]
+end
\ No newline at end of file
diff --git a/app/controllers/ru_captcha/captcha_controller.rb b/app/controllers/ru_captcha/captcha_controller.rb
index c85afbf..a77ecea 100644
--- a/app/controllers/ru_captcha/captcha_controller.rb
+++ b/app/controllers/ru_captcha/captcha_controller.rb
@@ -3,11 +3,13 @@ module RuCaptcha
def index
headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
headers['Pragma'] = 'no-cache'
+ data = generate_rucaptcha
+ opts = { disposition: 'inline', type: 'image/gif' }
if Gem.win_platform?
- send_file generate_rucaptcha, disposition: 'inline', type: 'image/png'
+ send_file data, opts
else
- send_data generate_rucaptcha, disposition: 'inline', type: 'image/png'
+ send_data data, opts
end
end
end
diff --git a/ext/rucaptcha/colors.h b/ext/rucaptcha/colors.h
new file mode 100644
index 0000000..876ac31
--- /dev/null
+++ b/ext/rucaptcha/colors.h
@@ -0,0 +1,345 @@
+// Colors from
+// https://material.io/guidelines/style/color.html#color-ui-color-palette
+static char *colors[] = {
+ // Black 500 #000000
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\x11\x11\x11"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Red 500 #F44336
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xF4\x43\x36"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Pink 500 #E91E63
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xE9\x1E\x63"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Purple 500 #9C27B0
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\x9C\x27\xB0"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Deep Purple 500 #673AB7
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\x67\x3A\xB7"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Indigo 500 #3F51B5
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\x3F\x51\xB5"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Blue 500 #2196F3
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\x21\x96\xF3"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Light Blue 500 #03A9F4
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\x03\xA9\xF4"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Cyan 500 #00BCD4
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\x00\xBC\xD4"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Teal 500 #009688
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\x00\x96\x88"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Green 500 #4CAF50
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\x4C\xAF\x50"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Light Green 500 #8BC34A
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\x8B\xC3\x4A"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Lime 500 #CDDC39
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xCD\xDC\x39"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Yellow 500 #FFEB3B
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xFF\xEB\x3B"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Amber 500 #FFC107
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xFF\xC1\x07"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Orange 500 #FF9800
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xFF\x98\x00"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Deep Orange 500 #FF5722
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xFF\x57\x22"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
+
+ // Brown 500 #795548
+ "GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\x79\x55\x48"
+ "\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04"
+};
\ No newline at end of file
diff --git a/ext/rucaptcha/extconf.rb b/ext/rucaptcha/extconf.rb
new file mode 100644
index 0000000..dfa482c
--- /dev/null
+++ b/ext/rucaptcha/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('rucaptcha/rucaptcha')
\ No newline at end of file
diff --git a/ext/rucaptcha/font.h b/ext/rucaptcha/font.h
new file mode 100644
index 0000000..e5ab712
--- /dev/null
+++ b/ext/rucaptcha/font.h
@@ -0,0 +1,27 @@
+static int8_t lt0[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-4,11,7,5,3,1,0,0,0,1,3,7,13,-100,-2,11,3,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,-1,7,0,0,0,0,0,0,3,9,11,9,3,0,0,0,0,13,-100,9,0,0,0,0,0,0,3,-5,3,0,0,0,7,-100,5,0,0,0,0,0,1,13,-5,9,0,0,0,1,-100,7,0,0,0,0,1,13,-6,13,0,0,0,0,-100,-1,9,1,0,5,13,-8,0,0,0,0,13,-100,-14,0,0,0,0,11,-100,-14,0,0,0,0,11,-100,-14,0,0,0,0,11,-100,-12,13,5,0,0,0,0,11,-100,-8,13,9,5,1,0,0,0,0,0,0,11,-100,-4,13,7,3,1,0,0,0,0,1,1,0,0,0,0,11,-100,-2,13,5,0,0,0,0,0,5,9,13,-2,0,0,0,0,11,-100,-1,13,1,0,0,0,0,7,-6,0,0,0,0,11,-100,13,1,0,0,0,0,13,-7,0,0,0,0,11,-100,5,0,0,0,0,5,-8,0,0,0,0,11,-100,0,0,0,0,0,11,-8,0,0,0,0,11,-100,0,0,0,0,0,13,-7,13,0,0,0,0,11,-100,1,0,0,0,0,-7,9,0,0,0,0,0,9,-3,9,-100,5,0,0,0,0,3,13,-3,11,3,0,0,0,0,0,0,0,9,13,3,5,-100,13,0,0,0,0,0,0,1,1,0,0,0,1,11,9,0,0,0,0,0,0,1,13,-100,-1,11,1,0,0,0,0,0,0,0,0,5,-3,9,0,0,0,0,0,11,-100,-2,13,7,3,0,0,0,3,7,13,-5,9,0,1,3,9,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt1[]={-100,-100,-4,13,5,0,3,-100,-3,11,1,0,0,0,7,-100,-2,7,0,0,0,0,0,3,-100,13,3,0,0,0,0,0,0,5,-100,1,0,0,0,0,0,0,0,9,-100,1,0,0,0,0,0,0,0,13,-100,13,3,0,0,0,0,0,1,-100,-2,5,0,0,0,0,5,-100,-3,0,0,0,0,9,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,9,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,3,13,9,5,3,1,0,0,1,3,5,9,-100,-3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,13,-100,-3,0,0,0,0,0,5,13,-2,13,11,9,5,0,0,0,0,1,13,-100,-3,0,0,0,0,1,-8,13,1,0,0,0,5,-100,-3,3,0,0,0,5,-9,13,0,0,0,0,11,-100,-3,0,0,0,0,9,-10,7,0,0,0,5,-100,-3,1,0,0,0,11,-10,13,0,0,0,0,-100,-3,3,0,0,0,11,-11,3,0,0,0,11,-100,-3,1,0,0,0,11,-11,7,0,0,0,7,-100,-3,0,0,0,0,11,-11,9,0,0,0,3,-100,-3,0,0,0,0,11,-11,11,0,0,0,1,-100,-3,0,0,0,0,11,-11,11,0,0,0,1,-100,-3,0,0,0,0,11,-11,11,0,0,0,0,-100,-3,0,0,0,0,11,-11,9,0,0,0,0,-100,-3,0,0,0,0,11,-11,7,0,0,0,3,-100,-3,0,0,0,0,11,-11,3,0,0,0,7,-100,-3,0,0,0,0,11,-11,0,0,0,0,11,-100,-3,0,0,0,0,11,-10,9,0,0,0,3,-100,-3,0,0,0,0,9,-10,3,0,0,0,11,-100,-3,0,0,0,0,3,-9,11,0,0,0,5,-100,-2,13,0,0,0,0,0,9,-7,11,1,0,0,3,-100,-2,7,0,0,0,0,0,0,7,13,-2,13,9,3,0,0,0,3,13,-100,-2,13,0,0,5,13,11,1,0,0,0,0,0,0,0,0,0,7,-100,-3,9,11,-4,7,3,1,0,0,1,5,9,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt2[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-6,13,7,3,1,0,0,1,3,7,13,-100,-5,9,0,0,0,0,0,0,0,0,0,0,5,13,-100,-3,13,3,0,0,0,5,13,13,7,0,0,0,0,0,1,13,-100,-2,13,1,0,0,0,9,-4,7,0,0,0,0,0,1,-100,-1,13,1,0,0,0,9,-6,5,0,0,0,0,0,13,-100,-1,5,0,0,0,3,-8,1,0,0,0,3,-100,13,0,0,0,0,11,-8,13,3,0,3,-100,7,0,0,0,1,-100,5,0,0,0,5,-100,3,0,0,0,9,-100,1,0,0,0,11,-100,0,0,0,0,11,-100,0,0,0,0,11,-100,0,0,0,0,11,-100,0,0,0,0,9,-100,1,0,0,0,5,-100,5,0,0,0,0,13,-100,11,0,0,0,0,7,-100,-1,3,0,0,0,0,13,-100,-1,11,0,0,0,0,3,-12,9,-100,-2,7,0,0,0,0,3,13,-8,9,1,3,-100,-3,5,0,0,0,0,1,9,-5,9,3,0,0,11,-100,-4,5,0,0,0,0,0,0,1,1,1,0,0,0,0,11,-100,-5,9,1,0,0,0,0,0,0,0,0,0,3,13,-100,-7,11,7,3,1,0,1,3,7,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt3[]={-100,-100,-100,-100,-18,11,3,0,-100,-16,13,3,0,0,0,-100,-14,9,3,0,0,0,0,0,-100,-13,3,0,0,0,0,0,0,0,-100,-13,0,0,0,0,0,0,0,0,-100,-13,9,1,0,0,0,0,0,0,-100,-15,13,5,0,0,0,0,-100,-17,1,0,0,0,-100,-17,3,0,0,0,-100,-17,1,0,0,0,-100,-17,0,0,0,0,-100,-16,13,0,0,0,0,-100,-16,13,0,0,0,0,-100,-6,11,5,3,1,0,0,1,5,9,13,13,0,0,0,0,-100,-4,13,3,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,-100,-3,13,1,0,0,0,0,5,11,-1,13,11,3,0,0,0,0,0,0,-100,-2,13,1,0,0,0,0,7,-6,11,0,0,0,0,0,-100,-2,3,0,0,0,0,9,-8,11,0,0,0,0,-100,-1,9,0,0,0,0,7,-9,11,0,0,0,0,-100,-1,1,0,0,0,0,13,-9,11,0,0,0,0,-100,11,0,0,0,0,3,-10,11,0,0,0,0,-100,5,0,0,0,0,13,-10,11,0,0,0,0,-100,3,0,0,0,3,-11,11,0,0,0,0,-100,0,0,0,0,7,-11,11,0,0,0,0,-100,0,0,0,0,11,-11,11,0,0,0,0,-100,0,0,0,0,11,-11,11,0,0,0,0,-100,0,0,0,0,11,-11,11,0,0,0,0,-100,1,0,0,0,9,-11,11,0,0,0,0,-100,3,0,0,0,7,-11,11,0,0,0,0,-100,7,0,0,0,3,-11,11,0,0,0,0,-100,13,0,0,0,0,13,-10,13,0,0,0,0,-100,-1,3,0,0,0,5,-11,0,0,0,0,-100,-1,13,0,0,0,0,11,-10,0,0,0,0,-100,-2,7,0,0,0,1,13,-8,13,0,0,0,0,13,-100,-3,5,0,0,0,1,11,-7,5,0,0,0,0,9,-100,-4,5,0,0,0,0,3,9,13,-1,13,11,1,0,0,0,0,0,0,0,5,-100,-5,9,1,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,1,13,-100,-7,9,3,1,0,0,3,7,13,-1,11,1,0,1,5,7,11,-100,-18,13,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt4[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-7,13,5,1,1,0,1,3,9,13,-100,-6,5,0,0,0,0,0,0,0,0,0,9,-100,-4,11,1,0,0,3,11,-1,13,7,1,0,0,0,9,-100,-3,9,0,0,0,1,13,-5,3,0,0,1,-100,-2,9,0,0,0,0,13,-6,11,0,0,0,9,-100,-1,13,0,0,0,0,9,-8,0,0,0,1,-100,-1,5,0,0,0,0,13,-8,3,0,0,0,11,-100,-1,0,0,0,0,0,-8,13,1,0,0,0,5,-100,9,0,0,0,0,0,3,11,-4,13,11,1,0,0,0,0,1,-100,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,-100,1,0,0,0,1,13,-100,0,0,0,0,11,-100,0,0,0,0,11,-100,1,0,0,0,9,-100,3,0,0,0,7,-100,7,0,0,0,5,-100,13,0,0,0,0,11,-100,-1,5,0,0,0,1,13,-100,-1,13,1,0,0,0,1,13,-10,13,11,-100,-2,11,0,0,0,0,1,13,-8,13,1,1,-100,-3,11,0,0,0,0,0,7,13,-4,11,7,0,0,9,-100,-4,11,1,0,0,0,0,0,1,1,1,0,0,0,0,7,-100,-5,13,5,0,0,0,0,0,0,0,0,0,1,9,-100,-7,13,7,3,0,0,0,1,5,9,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt5[]={-100,-100,-100,-100,-9,13,9,3,1,0,1,5,13,-100,-8,7,0,0,0,0,0,0,0,3,-100,-7,3,0,0,0,0,0,0,0,0,1,-100,-6,5,0,0,0,0,0,0,0,0,0,3,-100,-5,13,0,0,3,13,9,1,0,0,0,0,11,-100,-5,9,0,0,13,-2,13,5,0,1,9,-100,-5,5,0,0,-100,-5,1,0,1,-100,-5,1,0,0,-100,-5,0,0,0,-100,-5,0,0,0,13,-100,-5,0,0,0,9,-100,-5,0,0,0,7,-100,-5,0,0,0,5,-100,-3,13,7,0,0,0,0,9,-1,13,11,13,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,-1,11,13,-1,7,0,0,0,0,5,-1,13,11,13,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,7,-100,-3,13,5,0,0,0,0,0,7,13,-100,-1,5,0,0,0,0,0,0,0,0,0,0,0,1,11,-100,-1,7,1,0,0,0,0,0,0,0,0,1,3,7,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt6[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-7,11,7,3,1,0,0,1,3,7,13,-4,13,7,5,7,11,-100,-5,11,3,0,0,0,0,0,0,0,0,0,0,5,13,13,5,0,0,0,0,0,-100,-4,9,0,0,0,5,13,-1,13,9,3,0,0,0,0,0,0,0,0,0,0,0,1,-100,-3,11,0,0,0,5,-6,5,0,0,0,0,0,11,13,9,3,0,9,-100,-2,13,0,0,0,0,13,-7,1,0,0,0,0,13,-100,-2,1,0,0,0,7,-8,7,0,0,0,0,7,-100,-2,0,0,0,0,9,-8,11,0,0,0,0,3,-100,-2,0,0,0,0,11,-9,0,0,0,0,1,-100,-2,0,0,0,0,11,-9,0,0,0,0,0,-100,-2,0,0,0,0,9,-8,13,0,0,0,0,1,-100,-2,3,0,0,0,5,-8,9,0,0,0,0,7,-100,-2,13,1,0,0,0,13,-7,5,0,0,0,0,13,-100,-3,11,0,0,0,3,13,-5,7,0,0,0,0,11,-100,-4,7,0,0,0,1,9,13,-1,13,7,0,0,0,1,11,-100,-4,13,0,0,0,0,0,0,0,0,0,0,0,5,13,-100,-4,13,0,0,0,0,0,0,1,3,5,9,-100,-2,13,5,0,11,-100,-1,13,1,0,0,-100,-1,3,0,0,0,1,7,13,-100,-1,0,0,0,0,0,0,0,1,3,7,9,11,13,-100,-1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,5,11,-100,-2,11,7,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,11,-100,-4,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,-3,9,1,0,3,9,13,13,11,7,3,0,0,0,0,0,0,0,0,0,13,-100,-1,7,1,0,0,9,-8,11,7,3,0,0,0,0,0,5,-100,9,0,0,0,3,-13,11,1,0,0,1,-100,1,0,0,0,9,-15,0,0,0,-100,0,0,0,0,9,-14,13,0,0,1,-100,3,0,0,0,1,-14,7,0,0,5,-100,11,0,0,0,0,5,-12,11,0,0,0,13,-100,-1,11,1,0,0,0,1,7,11,13,-1,13,13,11,9,5,3,1,0,0,3,13,-100,-3,9,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,-100,-6,9,7,3,1,1,0,0,1,1,3,7,11,-100,-101};
+static int8_t lt7[]={-100,-100,-100,-100,-4,13,7,1,9,-100,-2,13,7,0,0,0,3,-100,-1,7,0,0,0,0,0,5,-100,1,0,0,0,0,0,0,7,-100,3,0,0,0,0,0,0,7,-100,13,7,0,0,0,0,0,9,-100,-2,5,0,0,0,0,9,-100,-2,11,0,0,0,0,9,-100,-3,0,0,0,0,9,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-5,11,5,1,0,1,7,-100,-3,0,0,0,0,11,-3,13,3,0,0,0,0,0,0,3,-100,-3,0,0,0,0,11,-2,7,0,0,0,0,0,0,0,0,0,9,-100,-3,0,0,0,0,11,11,3,0,5,11,-1,13,9,1,0,0,0,3,-100,-3,0,0,0,0,3,0,1,11,-6,1,0,0,0,13,-100,-3,0,0,0,0,0,5,-8,11,0,0,0,11,-100,-3,0,0,0,0,11,-10,0,0,0,7,-100,-3,0,0,0,0,13,-10,0,0,0,7,-100,-3,0,0,0,0,11,-10,0,0,0,7,-100,-3,0,0,0,0,11,-10,0,0,0,7,-100,-3,0,0,0,0,13,-10,0,0,0,9,-100,-3,0,0,0,0,13,-10,0,0,0,9,-100,-3,0,0,0,0,-11,0,0,0,11,-100,-3,0,0,0,1,-11,0,0,0,13,-100,-3,0,0,0,1,-11,0,0,0,13,-100,-3,0,0,0,3,-11,0,0,0,-100,-3,0,0,0,3,-11,0,0,0,-100,-3,0,0,0,3,-11,0,0,0,-100,-3,0,0,0,3,-10,13,0,0,0,13,-100,-3,0,0,0,1,-10,13,0,0,0,11,-100,-2,9,0,0,0,0,-10,11,0,0,0,5,-100,-1,7,0,0,0,0,0,5,13,-7,13,3,0,0,0,0,7,-100,5,0,0,0,0,0,0,0,0,3,-5,1,0,0,0,0,0,0,1,3,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt8[]={-100,-100,-100,-100,-3,5,1,0,3,11,-100,-2,7,0,0,0,0,0,11,-100,-2,1,0,0,0,0,0,5,-100,-2,0,0,0,0,0,0,5,-100,-2,5,0,0,0,0,0,11,-100,-3,7,0,0,3,9,-100,-4,13,-100,-100,-100,-100,-100,-100,-100,-4,11,3,0,9,-100,-2,9,3,0,0,0,9,-100,11,1,0,0,0,0,0,7,-100,1,0,0,0,0,0,0,7,-100,1,0,0,0,0,0,0,9,-100,-1,11,0,0,0,0,0,9,-100,-2,7,0,0,0,0,11,-100,-3,0,0,0,0,13,-100,-3,1,0,0,0,-100,-3,1,0,0,0,13,-100,-3,1,0,0,0,13,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-2,13,0,0,0,0,7,-100,-2,13,0,0,0,0,1,-100,-2,7,0,0,0,0,0,9,-100,7,0,0,0,0,0,0,0,0,3,-100,9,5,1,1,0,0,1,1,3,5,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt9[]={-100,-100,-100,-100,-6,5,0,1,5,13,-100,-5,5,0,0,0,0,1,-100,-5,1,0,0,0,0,0,13,-100,-5,0,0,0,0,0,0,-100,-5,5,0,0,0,0,3,-100,-6,7,1,0,5,13,-100,-100,-100,-100,-100,-100,-100,-100,-6,13,7,3,0,13,-100,-5,7,0,0,0,0,11,-100,-3,7,1,0,0,0,0,0,11,-100,-2,13,0,0,0,0,0,0,0,11,-100,-3,11,3,0,0,0,0,0,11,-100,-5,9,0,0,0,0,11,-100,-6,1,0,0,0,11,-100,-6,3,0,0,0,11,-100,-6,5,0,0,0,11,-100,-6,5,0,0,0,11,-100,-6,5,0,0,0,11,-100,-6,5,0,0,0,11,-100,-6,3,0,0,0,11,-100,-6,3,0,0,0,11,-100,-6,1,0,0,0,11,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,-100,-6,1,0,0,0,-100,-6,1,0,0,1,-100,-6,1,0,0,3,-100,-6,0,0,0,5,-100,-6,0,0,0,7,-100,-6,0,0,0,11,-100,11,0,0,0,5,5,0,0,5,-100,3,0,0,0,0,0,0,3,-100,0,0,0,0,0,0,0,13,-100,1,0,0,0,0,0,11,-100,13,3,0,0,3,11,-100,-100,-101};
+static int8_t lt10[]={-100,-100,-100,-100,-6,9,1,13,-100,-3,13,5,0,0,0,11,-100,-1,13,5,0,0,0,0,0,11,-100,13,1,0,0,0,0,0,0,11,-100,3,0,0,0,0,0,0,0,11,-100,11,3,0,0,0,0,0,0,11,-100,-2,13,0,0,0,0,0,11,-100,-3,9,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-7,3,0,0,0,0,0,0,0,0,0,3,-100,-4,0,0,0,0,11,-7,5,0,0,0,0,0,0,0,1,7,13,-100,-4,0,0,0,0,11,-8,9,0,0,0,1,9,-100,-4,0,0,0,0,11,-7,13,1,0,0,7,-100,-4,0,0,0,0,11,-7,5,0,3,13,-100,-4,0,0,0,0,11,-6,5,0,5,-100,-4,0,0,0,0,11,-5,5,1,11,-100,-4,0,0,0,0,11,-3,11,3,1,-100,-4,0,0,0,0,11,-1,11,3,0,0,1,-100,-4,0,0,0,0,11,9,0,0,0,0,0,11,-100,-4,0,0,0,0,0,0,1,0,0,0,0,3,-100,-4,0,0,0,0,0,9,-1,11,1,0,0,0,9,-100,-4,0,0,0,0,5,-4,3,0,0,0,11,-100,-4,0,0,0,0,11,-4,13,1,0,0,0,13,-100,-4,0,0,0,0,11,-5,11,0,0,0,1,13,-100,-4,0,0,0,0,11,-6,3,0,0,0,3,-100,-4,0,0,0,0,11,-6,11,0,0,0,0,7,-100,-4,0,0,0,0,11,-7,3,0,0,0,0,7,-100,-3,13,0,0,0,0,11,-7,13,0,0,0,0,0,7,-100,-2,13,3,0,0,0,0,7,-7,9,0,0,0,0,0,0,3,11,-100,-1,1,0,0,0,0,0,0,0,0,1,3,-4,0,0,0,0,0,0,0,0,0,0,3,-100,-1,7,1,0,0,0,0,0,0,0,0,7,-4,3,0,0,0,0,0,0,1,1,5,9,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt11[]={-100,-100,-100,-6,11,7,11,-100,-4,11,3,0,0,5,-100,-3,5,0,0,0,0,5,-100,-1,11,1,0,0,0,0,0,7,-100,7,0,0,0,0,0,0,0,7,-100,0,0,0,0,0,0,0,0,9,-100,7,0,0,0,0,0,0,0,9,-100,-2,9,1,0,0,0,0,9,-100,-3,11,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,7,-100,-3,5,0,0,0,0,0,13,-100,-1,9,1,0,0,0,0,0,0,0,1,9,-100,-1,5,1,0,0,0,0,0,0,0,1,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt12[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-5,11,5,0,-21,7,1,0,3,9,-100,-4,7,0,0,0,13,-4,11,5,1,1,0,1,7,-7,11,3,0,0,0,0,0,5,-100,-2,11,1,0,0,0,0,11,-2,9,1,0,0,0,0,0,0,0,9,-4,13,5,0,0,0,0,0,0,0,0,7,-100,13,3,0,0,0,0,0,0,7,13,3,0,0,0,1,0,0,0,0,0,0,7,-1,13,7,0,0,0,0,0,0,0,0,0,0,0,11,-100,3,0,0,0,0,0,0,0,1,0,0,5,11,-3,11,0,0,0,0,0,0,0,3,9,13,13,-3,7,0,0,0,0,5,-100,13,3,0,0,0,0,0,0,0,7,13,-6,3,0,0,0,0,0,9,-8,5,0,0,0,1,-100,-2,11,0,0,0,0,0,3,-8,9,0,0,0,0,7,-9,11,0,0,0,0,-100,-3,3,0,0,0,0,7,-8,13,0,0,0,0,-10,11,0,0,0,0,-100,-3,7,0,0,0,0,11,-9,0,0,0,0,-10,11,0,0,0,1,-100,-3,11,0,0,0,0,11,-9,0,0,0,0,-10,11,0,0,0,3,-100,-3,13,0,0,0,0,11,-8,13,0,0,0,0,-10,11,0,0,0,5,-100,-3,13,0,0,0,0,11,-8,11,0,0,0,0,-10,11,0,0,0,5,-100,-4,0,0,0,0,13,-8,9,0,0,0,0,-10,11,0,0,0,5,-100,-4,0,0,0,0,13,-8,11,0,0,0,0,-10,11,0,0,0,3,-100,-4,0,0,0,0,13,-8,11,0,0,0,0,-10,11,0,0,0,0,-100,-3,13,0,0,0,1,-9,13,0,0,0,0,-10,11,0,0,0,0,-100,-3,11,0,0,0,13,-10,0,0,0,0,-10,11,0,0,0,0,-100,-4,0,0,0,11,-10,0,0,0,0,-10,11,0,0,0,0,-100,-3,13,0,0,0,3,-9,13,0,0,0,0,13,-9,9,0,0,0,0,-100,-3,7,0,0,0,0,13,-8,11,0,0,0,0,11,-9,7,0,0,0,0,13,-100,-3,3,0,0,0,0,9,-8,5,0,0,0,0,5,-9,5,0,0,0,0,7,-100,-1,13,3,0,0,0,0,0,1,11,-6,9,0,0,0,0,0,0,3,-7,11,1,0,0,0,0,1,13,-100,11,0,0,0,0,0,0,0,0,0,3,-4,3,0,0,0,0,0,0,0,0,5,-5,1,0,0,0,0,0,0,0,0,9,-100,13,1,0,0,0,0,0,0,0,1,9,-4,1,0,0,0,0,0,0,0,1,5,-5,1,0,0,0,0,0,0,0,0,7,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt13[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-3,13,7,3,0,13,-5,13,7,1,0,0,3,7,-100,-2,5,0,0,0,0,-4,13,3,0,0,0,0,0,0,0,7,-100,7,1,0,0,0,0,0,-3,7,0,0,0,0,0,0,0,0,0,0,13,-100,1,0,0,0,0,0,0,13,9,1,0,5,11,13,-1,11,3,0,0,0,0,9,-100,13,3,0,0,0,0,0,1,1,7,-7,3,0,0,0,3,-100,-2,1,0,0,0,0,7,-9,13,0,0,0,1,-100,-2,7,0,0,0,0,-11,1,0,0,0,-100,-2,9,0,0,0,0,-11,1,0,0,0,13,-100,-2,11,0,0,0,0,-11,3,0,0,0,13,-100,-2,11,0,0,0,0,-11,5,0,0,0,11,-100,-2,11,0,0,0,0,-11,3,0,0,0,11,-100,-2,11,0,0,0,0,-11,1,0,0,0,11,-100,-2,11,0,0,0,0,-11,0,0,0,0,11,-100,-2,11,0,0,0,0,-11,0,0,0,0,11,-100,-2,11,0,0,0,0,-11,1,0,0,0,11,-100,-2,11,0,0,0,0,-11,3,0,0,0,11,-100,-2,11,0,0,0,0,-11,3,0,0,0,11,-100,-2,11,0,0,0,0,13,-10,5,0,0,0,11,-100,-2,11,0,0,0,0,13,-10,5,0,0,0,11,-100,-2,11,0,0,0,0,9,-10,5,0,0,0,9,-100,-2,7,0,0,0,0,5,-10,3,0,0,0,7,-100,-1,13,1,0,0,0,0,1,11,-7,11,5,0,0,0,0,0,3,9,-100,-1,1,0,0,0,0,0,0,0,0,3,-4,3,0,0,0,0,0,0,0,0,0,3,-100,-1,0,0,0,0,0,0,0,0,0,3,-4,5,1,0,0,0,0,0,0,0,0,1,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt14[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-7,13,7,3,1,0,0,1,5,9,-100,-6,7,0,0,0,0,0,0,0,0,0,1,7,-100,-4,11,1,0,0,1,9,13,-1,13,11,5,0,0,0,3,13,-100,-3,11,0,0,0,3,13,-6,13,1,0,0,0,13,-100,-2,11,0,0,0,1,13,-8,13,0,0,0,5,-100,-2,0,0,0,0,9,-10,5,0,0,0,11,-100,-1,7,0,0,0,1,-11,13,0,0,0,1,-100,-1,1,0,0,0,5,-12,1,0,0,0,9,-100,11,0,0,0,0,11,-12,5,0,0,0,3,-100,7,0,0,0,0,13,-12,9,0,0,0,0,-100,3,0,0,0,0,13,-12,11,0,0,0,0,-100,1,0,0,0,0,-13,11,0,0,0,1,-100,0,0,0,0,0,-13,11,0,0,0,1,-100,0,0,0,0,0,13,-12,11,0,0,0,0,-100,1,0,0,0,0,13,-12,9,0,0,0,1,-100,5,0,0,0,0,11,-12,5,0,0,0,3,-100,9,0,0,0,0,9,-12,3,0,0,0,7,-100,-1,1,0,0,0,5,-12,0,0,0,0,11,-100,-1,9,0,0,0,3,-11,13,0,0,0,3,-100,-2,3,0,0,0,13,-10,7,0,0,0,11,-100,-2,13,1,0,0,3,-9,13,0,0,0,7,-100,-3,13,1,0,0,3,13,-6,13,1,0,0,5,-100,-4,13,1,0,0,1,7,13,-3,9,0,0,0,7,-100,-6,7,0,0,0,0,0,0,0,0,0,3,11,-100,-7,13,7,3,0,0,0,0,3,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt15[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-6,11,7,-100,-4,11,3,0,0,7,11,5,3,0,0,0,1,5,9,-100,-2,11,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,-100,13,5,0,0,0,0,0,0,0,1,7,11,13,-1,13,3,0,0,0,5,-100,1,0,0,0,0,0,0,0,3,-7,7,0,0,0,7,-100,1,0,0,0,0,0,0,0,11,-8,7,0,0,0,13,-100,-1,11,5,0,0,0,0,0,11,-9,1,0,0,3,-100,-3,7,0,0,0,0,11,-9,5,0,0,0,11,-100,-3,9,0,0,0,0,11,-9,9,0,0,0,5,-100,-3,11,0,0,0,0,11,-9,11,0,0,0,0,13,-100,-3,11,0,0,0,0,11,-9,13,0,0,0,0,11,-100,-3,13,0,0,0,0,11,-10,0,0,0,0,11,-100,-3,13,0,0,0,0,11,-10,0,0,0,0,11,-100,-3,13,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,13,-100,-4,0,0,0,0,11,-10,0,0,0,0,13,-100,-4,0,0,0,0,13,-10,0,0,0,0,-100,-4,0,0,0,9,-11,0,0,0,3,-100,-4,0,0,0,3,-11,0,0,0,9,-100,-4,0,0,0,0,13,-10,0,0,0,13,-100,-4,0,0,0,0,11,-9,5,0,0,0,-100,-4,0,0,0,0,11,-8,7,0,0,0,7,-100,-4,0,0,0,0,5,-7,9,0,0,0,3,-100,-4,0,0,0,0,0,3,11,13,-3,9,0,0,0,1,-100,-4,0,0,0,0,5,7,0,0,0,1,1,0,0,0,1,13,-100,-4,0,0,0,0,11,-2,9,5,1,0,0,3,7,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,7,-100,-4,0,0,0,0,3,-100,-3,7,0,0,0,0,0,9,-100,-1,5,0,0,0,0,0,0,0,0,0,0,5,-100,-1,3,1,0,0,0,0,0,0,0,0,0,5,-100,-101};
+static int8_t lt16[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-19,7,11,-100,-6,11,5,1,0,0,1,5,11,-4,5,0,3,-100,-4,13,3,0,0,0,0,0,0,0,0,1,11,13,5,0,0,1,-100,-3,13,1,0,0,1,5,11,-3,11,3,0,0,0,0,0,3,-100,-2,13,1,0,0,3,-8,3,0,0,0,0,5,-100,-1,13,1,0,0,0,13,-8,7,0,0,0,0,5,-100,-1,3,0,0,0,5,-9,11,0,0,0,0,7,-100,9,0,0,0,0,11,-9,13,0,0,0,0,9,-100,3,0,0,0,0,-10,13,0,0,0,0,9,-100,1,0,0,0,1,-11,0,0,0,0,9,-100,0,0,0,0,3,-11,0,0,0,0,11,-100,0,0,0,0,5,-11,0,0,0,0,11,-100,0,0,0,0,9,-11,0,0,0,0,11,-100,0,0,0,0,11,-11,0,0,0,0,11,-100,0,0,0,0,11,-11,0,0,0,0,11,-100,1,0,0,0,11,-11,0,0,0,0,11,-100,3,0,0,0,9,-11,0,0,0,0,11,-100,7,0,0,0,5,-11,0,0,0,0,11,-100,11,0,0,0,0,-11,0,0,0,0,11,-100,-1,1,0,0,0,7,-9,11,0,0,0,0,11,-100,-1,9,0,0,0,0,13,-8,9,0,0,0,0,11,-100,-2,3,0,0,0,1,13,-7,5,0,0,0,0,11,-100,-2,13,3,0,0,0,1,9,13,-3,13,7,0,0,0,0,0,11,-100,-4,9,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,11,-100,-6,11,7,3,1,0,0,5,9,-1,13,0,0,0,0,11,-100,-16,0,0,0,0,13,-100,-16,0,0,0,0,13,-100,-16,0,0,0,0,13,-100,-16,0,0,0,0,13,-100,-15,13,0,0,0,0,13,-100,-15,9,0,0,0,0,11,-100,-15,1,0,0,0,0,5,-100,-12,7,5,1,0,0,0,0,0,0,1,3,9,-100,-11,13,1,0,0,0,0,0,0,0,0,0,0,7,-100,-101};
+static int8_t lt17[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-3,13,5,0,3,-5,9,3,1,0,0,3,-100,-1,11,3,0,0,0,0,-3,7,0,0,0,0,0,0,0,5,-100,9,0,0,0,0,0,0,-2,3,0,0,0,0,0,0,0,0,1,-100,0,0,0,0,0,0,0,11,3,0,0,0,0,0,0,0,0,0,1,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,-1,7,0,0,0,0,0,0,7,13,-2,11,7,3,1,3,11,-100,-2,3,0,0,0,0,3,-100,-2,7,0,0,0,0,9,-100,-2,11,0,0,0,0,13,-100,-2,13,0,0,0,0,-100,-3,0,0,0,0,-100,-3,0,0,0,0,13,-100,-3,0,0,0,0,13,-100,-3,0,0,0,0,13,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,9,-100,-1,13,3,0,0,0,0,1,13,-100,3,0,0,0,0,0,0,0,0,0,0,13,-100,5,1,0,0,0,0,0,0,0,0,3,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt18[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-3,13,7,1,0,1,3,9,11,9,9,13,-100,-2,13,1,0,0,0,0,0,0,0,0,0,5,-100,-2,1,0,5,13,-1,13,11,3,0,0,0,1,-100,-1,9,0,1,-6,9,0,0,0,13,-100,-1,3,0,9,-7,11,1,0,9,-100,-1,0,0,-9,13,1,5,-100,-1,0,0,11,-9,13,11,-100,13,0,0,1,13,-100,13,0,0,0,1,9,-100,-1,0,0,0,0,0,0,5,9,-100,-1,5,0,0,0,0,0,0,0,1,7,13,-100,-1,13,0,0,0,0,0,0,0,0,0,0,9,-100,-2,13,1,0,0,0,0,0,0,0,0,0,7,-100,-4,11,5,0,0,0,0,0,0,0,0,7,-100,-7,9,5,0,0,0,0,0,0,13,-100,-9,13,7,0,0,0,0,7,-100,-11,13,3,0,0,3,-100,-13,0,0,0,-100,7,5,-11,1,0,0,-100,1,0,5,-10,1,0,3,-100,0,0,0,3,-9,0,0,9,-100,1,0,0,0,3,13,-6,5,0,3,-100,7,0,0,0,0,1,7,11,13,13,9,3,0,1,13,-100,13,0,0,0,0,0,0,0,0,0,0,0,3,13,-100,-1,5,3,9,7,3,1,0,0,1,5,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt19[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-6,5,0,5,-100,-5,13,0,0,0,7,-100,-5,7,0,0,0,9,-100,-5,3,0,0,0,13,-100,-4,11,0,0,0,0,-100,-4,3,0,0,0,0,-100,-3,5,0,0,0,0,1,-100,-2,3,0,0,0,0,0,7,-100,13,1,0,0,0,0,0,0,1,11,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,5,13,-100,1,0,0,0,0,0,0,0,0,0,0,0,0,0,5,-100,-3,9,0,0,0,0,7,13,-100,-4,0,0,0,0,11,-100,-4,1,0,0,0,11,-100,-4,1,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,1,0,0,0,11,-100,-4,3,0,0,0,11,-100,-4,5,0,0,0,11,-100,-4,3,0,0,0,11,-100,-4,3,0,0,0,11,-100,-4,1,0,0,0,9,-100,-4,0,0,0,0,5,-100,-4,0,0,0,0,1,-100,-4,1,0,0,0,0,11,-100,-4,3,0,0,0,0,1,13,-1,9,5,1,3,-100,-4,9,0,0,0,0,0,0,0,0,0,0,5,-100,-5,5,0,0,0,0,0,0,0,0,5,-100,-6,9,3,1,0,0,1,5,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt20[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-4,13,9,1,0,13,-11,11,5,1,5,-100,-2,11,3,0,0,0,0,11,-8,11,5,0,0,0,0,1,-100,13,3,0,0,0,0,0,0,11,-6,7,1,0,0,0,0,0,0,7,-100,5,0,0,0,0,0,0,0,11,-5,5,0,0,0,0,0,0,0,0,11,-100,11,1,0,0,0,0,0,0,11,-5,9,0,0,0,0,0,0,0,0,11,-100,-2,11,1,0,0,0,0,11,-6,13,7,3,0,0,0,0,0,11,-100,-3,9,0,0,0,0,11,-9,9,0,0,0,0,11,-100,-3,11,0,0,0,0,11,-10,0,0,0,0,11,-100,-3,13,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,1,0,0,0,11,-9,13,0,0,0,0,11,-100,-4,1,0,0,0,11,-9,5,0,0,0,0,11,-100,-4,5,0,0,0,7,-8,7,0,0,0,0,0,11,-100,-4,7,0,0,0,0,13,-5,13,5,0,0,0,0,0,0,11,-100,-4,13,0,0,0,0,1,11,-1,13,11,5,0,0,7,5,0,0,0,0,3,13,-100,-5,3,0,0,0,0,0,0,0,0,0,3,13,-2,0,0,0,0,0,0,7,-100,-5,11,0,0,0,0,0,0,0,1,9,-4,0,0,0,0,0,0,0,-100,-6,13,5,1,0,1,3,9,-6,3,1,3,7,9,11,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt21[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-6,13,9,1,3,13,-5,13,1,0,0,0,0,1,3,9,-100,1,0,0,0,0,0,0,0,0,0,1,-5,1,0,0,0,0,0,0,0,0,9,-100,3,0,0,0,0,0,0,0,0,0,5,-5,3,0,0,0,0,0,0,0,0,13,-100,-1,9,3,0,0,0,0,0,5,13,-7,13,9,0,0,0,0,1,11,-100,-3,7,0,0,0,0,-11,7,0,0,5,-100,-4,0,0,0,0,9,-10,9,0,5,-100,-4,5,0,0,0,1,-10,5,0,11,-100,-4,11,0,0,0,0,9,-9,0,1,-100,-5,1,0,0,0,3,-8,9,0,7,-100,-5,7,0,0,0,0,13,-7,3,0,13,-100,-5,13,0,0,0,0,7,-6,13,0,3,-100,-6,3,0,0,0,1,-6,7,0,11,-100,-6,9,0,0,0,0,9,-5,0,1,-100,-6,13,0,0,0,0,3,-4,7,0,7,-100,-7,5,0,0,0,0,11,-3,1,0,13,-100,-7,11,0,0,0,0,1,-2,9,0,5,-100,-8,1,0,0,0,0,5,-1,1,0,11,-100,-8,7,0,0,0,0,0,0,0,3,-100,-8,13,0,0,0,0,0,0,0,9,-100,-9,3,0,0,0,0,0,1,-100,-9,9,0,0,0,0,0,7,-100,-10,0,0,0,0,0,13,-100,-10,5,0,0,0,1,-100,-10,13,1,0,0,7,-100,-11,11,1,5,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt22[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-29,13,-100,5,0,0,1,1,1,3,3,5,7,-3,7,0,0,0,0,0,0,0,0,0,11,-4,3,0,0,0,0,0,0,1,3,11,-100,5,0,0,0,0,0,0,0,1,7,-3,9,0,0,0,0,0,0,0,0,1,11,-4,9,1,0,0,0,0,0,0,1,13,-100,-1,13,5,0,0,0,0,0,13,-5,13,5,0,0,0,0,0,3,-8,9,0,0,0,0,5,-100,-3,5,0,0,0,0,-8,11,0,0,0,0,9,-9,9,0,0,9,-100,-4,1,0,0,0,13,-8,11,0,0,0,3,-10,0,3,-100,-4,7,0,0,0,11,-8,13,0,0,0,0,13,-8,9,0,11,-100,-4,13,0,0,0,7,-8,11,0,0,0,0,7,-8,1,1,-100,-5,5,0,0,1,-8,7,0,0,0,0,3,-8,5,11,-100,-5,11,0,0,0,9,-7,1,0,0,0,0,0,13,-100,-6,0,0,0,3,-6,9,0,3,13,0,0,0,7,-6,5,-100,-6,3,0,0,0,13,-5,1,0,11,-1,3,0,0,3,-6,1,-100,-6,9,0,0,0,9,-4,11,0,3,-2,7,0,0,0,13,-4,11,1,-100,-6,13,0,0,0,3,-4,5,0,9,-2,13,0,0,0,7,-4,5,3,-100,-7,3,0,0,0,13,-3,1,1,-4,0,0,0,1,-4,1,7,-100,-7,9,0,0,0,5,-2,13,0,7,-4,5,0,0,0,9,-2,9,0,13,-100,-8,1,0,0,0,13,-1,7,1,-5,11,0,0,0,1,-2,1,3,-100,-8,7,0,0,0,1,13,1,5,-6,1,0,0,0,13,9,0,9,-100,-8,13,0,0,0,0,0,0,11,-6,7,0,0,0,1,0,1,-100,-9,3,0,0,0,0,3,-7,13,0,0,0,0,0,9,-100,-9,9,0,0,0,0,5,-8,3,0,0,0,0,13,-100,-9,13,0,0,0,0,11,-8,9,0,0,0,1,-100,-10,3,0,0,0,-10,3,0,0,5,-100,-10,11,0,0,7,-10,13,1,1,13,-100,-11,11,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt23[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-16,13,13,-1,13,9,5,1,0,1,5,13,-100,-1,3,0,0,0,0,0,0,0,0,1,7,-4,1,0,0,0,0,0,0,0,0,0,1,-100,-1,1,0,0,0,0,0,0,0,0,1,11,-4,7,0,0,0,0,0,0,0,0,0,5,-100,-2,13,7,0,0,0,0,0,0,13,-6,13,5,0,0,0,0,5,9,13,-100,-4,13,3,0,0,0,0,3,-7,13,0,0,5,13,-100,-6,3,0,0,0,0,5,-6,7,0,7,-100,-7,3,0,0,0,0,11,-4,11,0,9,-100,-8,5,0,0,0,1,-3,11,0,7,-100,-9,3,0,0,0,1,11,11,0,7,-100,-9,13,1,0,0,0,0,0,7,-100,-10,13,1,0,0,0,0,9,-100,-11,11,0,0,0,0,1,-100,-12,0,0,0,0,0,7,-100,-11,9,0,0,0,0,0,0,11,-100,-10,9,0,5,13,3,0,0,0,1,13,-100,-9,11,0,3,-2,13,1,0,0,0,1,13,-100,-8,11,0,3,13,-3,13,1,0,0,0,1,13,-100,-7,9,0,1,13,-5,11,0,0,0,0,1,13,-100,-6,9,0,0,7,-7,9,0,0,0,0,1,11,-100,-5,5,0,0,0,13,-8,7,0,0,0,0,0,9,-100,-3,13,3,0,0,0,0,13,-8,13,0,0,0,0,0,0,5,-100,9,3,1,0,0,0,0,0,0,1,11,-6,11,1,0,0,0,0,0,0,0,1,3,13,-100,3,0,0,0,0,0,0,0,0,0,3,-6,11,5,3,1,0,0,0,1,1,3,5,-100,13,13,13,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
+static int8_t lt24[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-1,13,13,-2,13,13,11,11,11,13,-6,11,11,11,11,11,11,11,11,13,-100,3,0,0,0,0,0,0,0,0,0,0,3,-4,1,0,0,0,0,0,0,0,0,1,-100,7,0,0,0,0,0,0,0,0,0,0,5,-4,3,0,0,0,0,0,0,0,0,9,-100,-2,11,5,0,0,0,0,0,0,11,-6,11,0,0,0,0,1,7,13,-100,-4,11,0,0,0,0,0,-8,9,0,0,1,13,-100,-5,7,0,0,0,0,13,-7,9,0,0,13,-100,-6,1,0,0,0,9,-7,5,0,5,-100,-6,7,0,0,0,3,-7,1,0,13,-100,-6,13,0,0,0,0,13,-5,11,0,1,-100,-7,5,0,0,0,7,-5,7,0,7,-100,-7,11,0,0,0,3,-5,1,0,11,-100,-8,1,0,0,0,13,-3,13,0,3,-100,-8,7,0,0,0,7,-3,7,0,9,-100,-8,13,0,0,0,3,-3,1,1,-100,-9,5,0,0,0,13,-1,9,0,7,-100,-9,11,0,0,0,3,13,1,0,13,-100,-10,1,0,0,0,0,0,3,-100,-10,9,0,0,0,0,0,9,-100,-11,1,0,0,0,1,-100,-11,5,0,0,0,7,-100,-11,9,0,0,0,13,-100,-11,13,0,0,3,-100,-12,0,0,9,-100,-12,0,1,-100,-11,13,0,7,-100,-11,7,0,11,-100,-11,1,0,-100,-2,7,0,1,7,-4,11,0,3,-100,-1,11,0,0,0,0,1,9,13,11,1,0,9,-100,-1,3,0,0,0,0,0,0,0,0,0,3,-100,-1,0,0,0,0,0,0,0,0,0,1,13,-100,-1,7,0,0,0,0,0,0,0,1,13,-100,-2,9,3,0,0,1,3,7,-100,-101};
+static int8_t *lt[]={lt0,lt1,lt2,lt3,lt0,lt5,lt0,lt7,lt8,lt9,lt10,lt11,lt12,lt13,lt14,lt15,lt16,lt17,lt18,lt19,lt20,lt21,lt22,lt23,lt24,};
+
diff --git a/ext/rucaptcha/rucaptcha.c b/ext/rucaptcha/rucaptcha.c
new file mode 100644
index 0000000..a39fbad
--- /dev/null
+++ b/ext/rucaptcha/rucaptcha.c
@@ -0,0 +1,214 @@
+// http://github.com/ITikhonov/captcha
+const int gifsize;
+void captcha(unsigned char im[70*200], unsigned char l[6]);
+void makegif(unsigned char im[70*200], unsigned char gif[gifsize], int style);
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "font.h"
+#include "colors.h"
+
+static int8_t *lt[];
+const int gifsize=17646;
+
+void makegif(unsigned char im[70*200], unsigned char gif[gifsize], int style) {
+ // tag ; widthxheight ; GCT:0:0:7 ; bgcolor + aspect // GCT
+ // Image Separator // left x top // widthxheight // Flags
+ // LZW code size
+ srand(time(NULL));
+ int color_len = (int) sizeof(colors) / sizeof(colors[0]);
+ int color_idx = rand() % color_len;
+ if (style == 0) {
+ color_idx = 0;
+ }
+ memcpy(gif,colors[color_idx],13+48+10+1);
+
+ int x,y;
+ unsigned char *i=im;
+ unsigned char *p=gif+13+48+10+1;
+ for(y=0;y<70;y++) {
+ *p++=250; // Data length 5*50=250
+ for(x=0;x<50;x++)
+ {
+ unsigned char a=i[0]>>4,b=i[1]>>4,c=i[2]>>4,d=i[3]>>4;
+
+ p[0]=16|(a<<5); // bbb10000
+ p[1]=(a>>3)|64|(b<<7); // b10000xb
+ p[2]=b>>1; // 0000xbbb
+ p[3]=1|(c<<1); // 00xbbbb1
+ p[4]=4|(d<<3); // xbbbb100
+ i+=4;
+ p+=5;
+ }
+ }
+
+ // Data length // End of LZW (b10001) // Terminator // GIF End
+ memcpy(gif+gifsize-4,"\x01" "\x11" "\x00" ";",4);
+}
+
+static const int8_t sw[200]={0, 4, 8, 12, 16, 20, 23, 27, 31, 35, 39, 43, 47, 50, 54, 58, 61, 65, 68, 71, 75, 78, 81, 84, 87, 90, 93, 96, 98, 101, 103, 105, 108, 110, 112, 114, 115, 117, 119, 120, 121, 122, 123, 124, 125, 126, 126, 127, 127, 127, 127, 127, 127, 127, 126, 126, 125, 124, 123, 122, 121, 120, 119, 117, 115, 114, 112, 110, 108, 105, 103, 101, 98, 96, 93, 90, 87, 84, 81, 78, 75, 71, 68, 65, 61, 58, 54, 50, 47, 43, 39, 35, 31, 27, 23, 20, 16, 12, 8, 4, 0, -4, -8, -12, -16, -20, -23, -27, -31, -35, -39, -43, -47, -50, -54, -58, -61, -65, -68, -71, -75, -78, -81, -84, -87, -90, -93, -96, -98, -101, -103, -105, -108, -110, -112, -114, -115, -117, -119, -120, -121, -122, -123, -124, -125, -126, -126, -127, -127, -127, -127, -127, -127, -127, -126, -126, -125, -124, -123, -122, -121, -120, -119, -117, -115, -114, -112, -110, -108, -105, -103, -101, -98, -96, -93, -90, -87, -84, -81, -78, -75, -71, -68, -65, -61, -58, -54, -50, -47, -43, -39, -35, -31, -27, -23, -20, -16, -12, -8, -4};
+
+
+#define MAX(x,y) ((x>y)?(x):(y))
+
+static int letter(int n, int pos, unsigned char im[70*200], unsigned char swr[200], uint8_t s1, uint8_t s2) {
+ int8_t *p=lt[n];
+ unsigned char *r=im+200*16+pos;
+ unsigned char *i=r;
+ int sk1=s1+pos;
+ int sk2=s2+pos;
+ int mpos=pos;
+ int row=0;
+ for(;*p!=-101;p++) {
+ if(*p<0) {
+ if(*p==-100) { r+=200; i=r; sk1=s1+pos; row++; continue; }
+ i+=-*p;
+ continue;
+ }
+
+ if(sk1>=200) sk1=sk1%200;
+ int skew=sw[sk1]/16;
+ sk1+=(swr[pos+i-r]&0x1)+1;
+
+ if(sk2>=200) sk2=sk2%200;
+ int skewh=sw[sk2]/70;
+ sk2+=(swr[row]&0x1);
+
+ unsigned char *x=i+skew*200+skewh;
+ mpos=MAX(mpos,pos+i-r);
+
+ if((x-im)<70*200) *x=(*p)<<4;
+ i++;
+ }
+ return mpos;
+}
+
+#define NDOTS 100
+
+uint32_t dr[NDOTS];
+
+static void line(unsigned char im[70*200], unsigned char swr[200], uint8_t s1) {
+ int x;
+ int sk1=s1;
+ for(x=0;x<199;x++) {
+ if(sk1>=200) sk1=sk1%200;
+ int skew=sw[sk1]/16;
+ sk1+=swr[x]&0x3+1;
+ unsigned char *i= im+(200*(45+skew)+x);
+ i[0]=0; i[1]=0; i[200]=0; i[201]=0;
+ }
+}
+
+static void dots(unsigned char im[70*200]) {
+ int n;
+ for(n=0;n0xf0 && i[1]<0xf0) { o[0]=0; o[1]=0; }
+ else if(i[0]<0xf0 && i[1]>0xf0) { o[0]=0; o[1]=0; }
+
+ i++;
+ o++;
+ }
+ }
+
+ memmove(im,om,sizeof(om));
+}
+
+static const char *letters="abcdafahijklmnopqrstuvwxyz";
+
+void captcha(unsigned char im[70*200], unsigned char l[6]) {
+ unsigned char swr[200];
+ uint8_t s1,s2;
+
+ int f=open("/dev/urandom",O_RDONLY);
+ read(f,l,5); read(f,swr,200); read(f,dr,sizeof(dr)); read(f,&s1,1); read(f,&s2,1);
+ close(f);
+
+ memset(im,0xff,200*70); s1=s1&0x7f; s2=s2&0x3f; l[0]%=25; l[1]%=25; l[2]%=25; l[3]%=25; l[4]%=25; l[5]=0;
+ int p=30; p=letter(l[0],p,im,swr,s1,s2); p=letter(l[1],p,im,swr,s1,s2); p=letter(l[2],p,im,swr,s1,s2); p=letter(l[3],p,im,swr,s1,s2); letter(l[4],p,im,swr,s1,s2);
+ line(im,swr,s1); dots(im); // blur(im); // filter(im);
+ l[0]=letters[l[0]]; l[1]=letters[l[1]]; l[2]=letters[l[2]]; l[3]=letters[l[3]]; l[4]=letters[l[4]];
+}
+
+// #ifdef CAPTCHA
+//
+// int main() {
+// char l[6];
+// unsigned char im[70*200];
+// unsigned char gif[gifsize];
+//
+// captcha(im,l);
+// makegif(im,gif);
+//
+// write(1,gif,gifsize);
+// write(2,l,5);
+//
+// return 0;
+// }
+//
+// #endif
+
+VALUE RuCaptcha = Qnil;
+
+void Init_rucaptcha();
+
+VALUE create(VALUE self, VALUE style);
+
+void Init_rucaptcha() {
+ RuCaptcha = rb_define_module("RuCaptcha");
+ rb_define_singleton_method(RuCaptcha, "create", create, 1);
+}
+
+VALUE create(VALUE self, VALUE style) {
+ char l[6];
+ unsigned char im[80*200];
+ unsigned char gif[gifsize];
+ int i_style = FIX2INT(style);
+
+ captcha(im, l);
+ makegif(im, gif, i_style);
+
+ VALUE result = rb_ary_new2(2);
+ rb_ary_push(result, rb_str_new2(l));
+ rb_ary_push(result, rb_str_new(gif, gifsize));
+
+ return result;
+}
+
+
diff --git a/lib/rucaptcha.rb b/lib/rucaptcha.rb
index 0c44b49..66cdec8 100644
--- a/lib/rucaptcha.rb
+++ b/lib/rucaptcha.rb
@@ -1,12 +1,12 @@
require 'rails'
require 'action_controller'
require 'active_support/all'
+require_relative 'rucaptcha/rucaptcha'
require_relative 'rucaptcha/version'
require_relative 'rucaptcha/configuration'
require_relative 'rucaptcha/controller_helpers'
require_relative 'rucaptcha/view_helpers'
require_relative 'rucaptcha/cache'
-require_relative 'rucaptcha/captcha'
require_relative 'rucaptcha/engine'
module RuCaptcha
@@ -14,12 +14,8 @@ module RuCaptcha
def config
return @config if defined?(@config)
@config = Configuration.new
- @config.len = 4
- @config.font_size = 45
- @config.implode = 0.3
- @config.cache_limit = 100
- @config.expires_in = 2.minutes
@config.style = :colorful
+ @config.expires_in = 2.minutes
if Rails.application
@config.cache_store = Rails.application.config.cache_store
else
@@ -31,6 +27,11 @@ module RuCaptcha
def configure(&block)
config.instance_exec(&block)
end
+
+ def generate()
+ style = config.style == :colorful ? 1 : 0
+ self.create(style)
+ end
end
end
diff --git a/lib/rucaptcha/cache.rb b/lib/rucaptcha/cache.rb
index 8d4a9fd..1416bfa 100644
--- a/lib/rucaptcha/cache.rb
+++ b/lib/rucaptcha/cache.rb
@@ -8,46 +8,4 @@ module RuCaptcha
@cache
end
end
-
- # File Cache
- module Cache
- def self.prepended(base)
- class << base
- prepend ClassMethods
- end
- end
-
- module ClassMethods
- def create(code)
- file_cache.fetch(code, expires_in: 1.days) do
- super(code)
- end
- end
-
- def random_chars
- if cached_codes.length >= RuCaptcha.config.cache_limit
- return cached_codes.sample
- end
-
- code = super
- cached_codes << code
- code
- end
-
- def file_cache
- return @file_cache if defined?(@file_cache)
-
- cache_path = Rails.root.join('tmp', 'cache', 'rucaptcha')
- FileUtils.mkdir_p(cache_path) unless File.exist? cache_path
- @file_cache = ActiveSupport::Cache::FileStore.new(cache_path)
- # clear expired captcha cache files on Process restart
- @file_cache.cleanup
- @file_cache
- end
-
- def cached_codes
- @cached_codes ||= []
- end
- end
- end
end
diff --git a/lib/rucaptcha/captcha.rb b/lib/rucaptcha/captcha.rb
deleted file mode 100644
index 51bf2da..0000000
--- a/lib/rucaptcha/captcha.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-require 'open3'
-
-module RuCaptcha
- class Captcha
- class << self
- # Genrate ranom RGB color
- def random_color
- if RuCaptcha.config.style == :colorful
- color1 = rand(56) + 15
- color2 = rand(10) + 140
- color = [color1, color2, rand(15)]
- color.shuffle!
- color
- else
- color_seed = rand(40) + 10
- [color_seed, color_seed, color_seed]
- end
- end
-
- # Genrate random Captcha code
- def random_chars
- chars = SecureRandom.hex(RuCaptcha.config.len / 2).downcase
- chars.gsub!(/[0ol1]/i, (rand(8) + 2).to_s)
- chars
- end
-
- # Create Captcha image by code
- def create(code)
- chars = code.split('')
- full_width = RuCaptcha.config.font_size * chars.size
- full_height = RuCaptcha.config.font_size
- size = "#{full_width}x#{full_height}"
-
- return convert_for_windows(size, code) if Gem.win_platform?
-
- opts = command_line_opts(chars, full_width)
- convert(size, opts)
- end
-
- private
-
- def command_line_opts(chars, full_width)
- font_size = RuCaptcha.config.font_size
- all_left = 20
- half_width = full_width / 2
- text_top = 0
- text_left = 0 - (font_size * 0.28).to_i
- text_width = font_size + text_left
-
- opts = { text: [], line: [] }
- rgbs = uniq_rgbs_for_each_chars(chars)
-
- chars.each_with_index do |char, i|
- rgb = RuCaptcha.config.style == :colorful ? rgbs[i] : rgbs[0]
- text_color = "rgba(#{rgb.join(',')}, 1)"
- line_color = "rgba(#{rgb.join(',')}, 0.6)"
- opts[:text] << %(-fill '#{text_color}' -draw 'text #{(text_left + text_width) * i + all_left},#{text_top} "#{char}"')
-
- left_y = rand_line_top(text_top, font_size)
- right_x = half_width + (half_width * 0.3).to_i
- right_y = rand_line_top(text_top, font_size)
- opts[:line] << %(-draw 'stroke #{line_color} line #{rand(10)},#{left_y} #{right_x},#{right_y}')
- end
- opts
- end
-
- def convert(size, opts)
- stroke_width = (RuCaptcha.config.font_size * 0.05).to_i + 1
- command = <<-CODE
- convert -size #{size} \
- -strokewidth #{stroke_width} \
- #{opts[:line].join(' ')} \
- -pointsize #{RuCaptcha.config.font_size} -weight 500 \
- #{opts[:text].join(' ')} \
- -wave #{rand(2) + 3}x#{rand(2) + 1} \
- -rotate #{rand(10) - 5} \
- -gravity NorthWest -sketch 1x10+#{rand(2)} \
- -fill none \
- -implode #{RuCaptcha.config.implode} -trim label:- png:-
- CODE
- command.strip!
- out, err, _st = Open3.capture3(command)
- warn " RuCaptcha #{err.strip}" if err.present?
- out
- end
-
- # Generate a simple captcha image for Windows Platform
- def convert_for_windows(size, code)
- png_file_path = Rails.root.join('tmp', 'cache', "#{code}.png")
- command = "convert -size #{size} xc:White -gravity Center -weight 12 -pointsize 20 -annotate 0 \"#{code}\" -trim #{png_file_path}"
- _out, err, _st = Open3.capture3(command)
- warn " RuCaptcha #{err.strip}" if err.present?
- png_file_path
- end
-
- # Geneate a uniq rgba colors for each chars
- def uniq_rgbs_for_each_chars(chars)
- rgbs = []
- chars.count.times do |i|
- color = random_color
- if i > 0
- preview_color = rgbs[i - 1]
- # Avoid color same as preview color
- if color.index(color.min) == preview_color.index(preview_color.min) &&
- color.index(color.max) == preview_color.index(preview_color.max)
- # adjust RGB order
- color = [color[1], color[2], color[0]]
- end
- end
- rgbs << color
- end
- rgbs
- end
-
- def rand_line_top(text_top, font_size)
- text_top + rand(font_size * 0.7).to_i
- end
-
- def warn(msg)
- msg = " RuCaptcha #{msg}"
- Rails.logger.error(msg)
- end
- end
- end
-end
diff --git a/lib/rucaptcha/configuration.rb b/lib/rucaptcha/configuration.rb
index 4330e33..d034143 100644
--- a/lib/rucaptcha/configuration.rb
+++ b/lib/rucaptcha/configuration.rb
@@ -1,20 +1,11 @@
module RuCaptcha
class Configuration
- # Image font size, default 45
- attr_accessor :font_size
- # Number of chars, default 4
- attr_accessor :len
- # implode, default 0.3
- attr_accessor :implode
# Store Captcha code where, this config more like Rails config.cache_store
# default: Rails application config.cache_store
attr_accessor :cache_store
- # Number of Captcha codes limit
- # set 0 to disable limit and file cache, default: 100
- attr_accessor :cache_limit
- # Color style, default: :colorful, allows: [:colorful, :black_white]
- attr_accessor :style
# rucaptcha expire time, default 2 minutes
attr_accessor :expires_in
+ # Color style, default: :colorful, allows: [:colorful, :black_white]
+ attr_accessor :style
end
end
diff --git a/lib/rucaptcha/controller_helpers.rb b/lib/rucaptcha/controller_helpers.rb
index a76488f..fe187e3 100644
--- a/lib/rucaptcha/controller_helpers.rb
+++ b/lib/rucaptcha/controller_helpers.rb
@@ -14,13 +14,13 @@ module RuCaptcha
# Generate a new Captcha
def generate_rucaptcha
- code = RuCaptcha::Captcha.random_chars
+ res = RuCaptcha.generate()
session_val = {
- code: code,
+ code: res[0],
time: Time.now.to_i
}
RuCaptcha.cache.write(rucaptcha_sesion_key_key, session_val, expires_in: RuCaptcha.config.expires_in)
- RuCaptcha::Captcha.create(code)
+ res[1]
end
# Verify captcha code
diff --git a/lib/rucaptcha/engine.rb b/lib/rucaptcha/engine.rb
index e76a1e6..e4ff30f 100644
--- a/lib/rucaptcha/engine.rb
+++ b/lib/rucaptcha/engine.rb
@@ -3,11 +3,6 @@ module RuCaptcha
isolate_namespace RuCaptcha
initializer 'rucaptcha.prepend.cache' do
- # enable cache if cache_limit less than 1
- if RuCaptcha.config.cache_limit >= 1
- RuCaptcha::Captcha.send(:prepend, RuCaptcha::Cache)
- end
-
cache_store = RuCaptcha.config.cache_store
store_name = cache_store.is_a?(Array) ? cache_store.first : cache_store
if [:memory_store, :null_store, :file_store].include?(store_name)
diff --git a/lib/rucaptcha/version.rb b/lib/rucaptcha/version.rb
index c05046e..78d10e8 100644
--- a/lib/rucaptcha/version.rb
+++ b/lib/rucaptcha/version.rb
@@ -1,3 +1,3 @@
module RuCaptcha
- VERSION = '1.2.0'
+ VERSION = '2.0.0'
end
diff --git a/lib/rucaptcha/view_helpers.rb b/lib/rucaptcha/view_helpers.rb
index c60bacd..a979654 100644
--- a/lib/rucaptcha/view_helpers.rb
+++ b/lib/rucaptcha/view_helpers.rb
@@ -5,8 +5,8 @@ module RuCaptcha
opts[:type] = 'text'
opts[:autocorrect] = 'off'
opts[:autocapitalize] = 'off'
- opts[:pattern] = '[0-9a-zA-Z]*'
- opts[:maxlength] = RuCaptcha.config.len
+ opts[:pattern] = '[a-zA-Z]*'
+ opts[:maxlength] = 5
opts[:autocomplete] = 'off'
tag(:input, opts)
end
diff --git a/rucaptcha.gemspec b/rucaptcha.gemspec
index 4e3393f..ff50488 100644
--- a/rucaptcha.gemspec
+++ b/rucaptcha.gemspec
@@ -8,12 +8,18 @@ Gem::Specification.new do |s|
s.version = RuCaptcha::VERSION
s.authors = 'Jason Lee'
s.email = 'huacnlee@gmail.com'
- s.files = Dir.glob('lib/**/*') + Dir.glob('app/**/*') + Dir.glob('config/**/*') + %w(README.md CHANGELOG.md)
+ s.files = Dir.glob('lib/**/*.{rb}') +
+ Dir.glob("ext/**/*.{h,c,rb}") +
+ Dir.glob('app/**/*') +
+ Dir.glob('config/**/*') +
+ %w[README.md CHANGELOG.md]
s.homepage = 'https://github.com/huacnlee/rucaptcha'
s.require_paths = ['lib']
+ s.extensions = %w[ext/rucaptcha/extconf.rb]
s.summary = 'This is a Captcha gem for Rails Application. It run ImageMagick command to draw Captcha image.'
s.license = "MIT"
s.required_ruby_version = ">= 2.0.0"
s.add_dependency 'railties', '>= 3.2'
+ s.add_development_dependency 'rake-compiler', '~> 1'
end
diff --git a/spec/cache_spec.rb b/spec/cache_spec.rb
deleted file mode 100644
index 7b03fca..0000000
--- a/spec/cache_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require 'spec_helper'
-
-describe RuCaptcha::Cache do
- before(:all) do
- RuCaptcha::Captcha.send(:prepend, RuCaptcha::Cache)
- end
-
- describe '.random_chars_with_cache' do
- it 'should generate max chars by config.cache_limit' do
- allow(RuCaptcha.config).to receive(:cache_limit).and_return(5)
- items = []
- 100.times do
- items << RuCaptcha::Captcha.random_chars
- end
- expect(items.uniq.length).to eq RuCaptcha.config.cache_limit
- expect(RuCaptcha::Captcha.cached_codes).to eq items.uniq
- end
- end
-
- describe '.create' do
- it 'should work' do
- expect(RuCaptcha::Captcha).to receive(:create).and_return('aabb')
- expect(RuCaptcha::Captcha.create('abcd')).to eq('aabb')
- end
- end
-end
diff --git a/spec/captcha_spec.rb b/spec/captcha_spec.rb
index e594bec..a7a79fc 100644
--- a/spec/captcha_spec.rb
+++ b/spec/captcha_spec.rb
@@ -1,64 +1,28 @@
require 'spec_helper'
-describe RuCaptcha::Captcha do
- describe '.random_chars' do
+describe RuCaptcha do
+ describe '.generate' do
+ it 'should work' do
+ res = RuCaptcha.generate()
+ expect(res.length).to eq(2)
+ expect(res[0].length).to eq(5)
+ expect(res[1]).not_to eq(nil)
+ end
+ end
+
+ describe '.create' do
it 'should len equal config.len' do
- expect(RuCaptcha::Captcha.random_chars.length).to eq(RuCaptcha.config.len)
+ res = RuCaptcha.create(0)
+ expect(res.length).to eq(2)
+ expect(res[0].length).to eq(5)
+ expect(res[1]).not_to eq(nil)
end
- it 'should return 0-9 and lower str' do
- expect(RuCaptcha::Captcha.random_chars).to match(/[a-z0-9]/)
- end
-
- it 'should not include [0ol1]' do
- 10_000.times do
- expect(RuCaptcha::Captcha.random_chars).not_to match(/[0ol1]/i)
- end
- end
- end
-
- describe '.random_color' do
- it 'should return colorful array' do
- allow(RuCaptcha.config).to receive(:style).and_return(:colorful)
- colors = RuCaptcha::Captcha.random_color
- expect(colors.uniq.size >= 2).to eq true
- colors1 = RuCaptcha::Captcha.random_color
- expect(colors).not_to eq colors1
- end
-
- it 'should return black color array' do
- allow(RuCaptcha.config).to receive(:style).and_return(:black_white)
- colors = RuCaptcha::Captcha.random_color
- expect(colors.uniq.size).to eq 1
- colors1 = RuCaptcha::Captcha.random_color
- expect(colors).not_to eq colors1
- end
- end
-
- describe '.rand_line_top' do
- it 'should work' do
- expect(RuCaptcha::Captcha.send(:rand_line_top, 1, 24)).to be_a(Integer)
- end
- end
-
- describe '.uniq_rgbs_for_each_chars' do
- let(:chars) { %w(a b c d e) }
- let(:colors) { RuCaptcha::Captcha.send(:uniq_rgbs_for_each_chars, chars) }
-
- it 'should work' do
- expect(colors.length).to eq chars.length
- expect(colors[0].length).to eq 3
- end
-
- it 'Be sure the color not same as preview color' do
- pre_rgb = nil
- colors.each do |rgb|
- if pre_rgb
- same = rgb.index(rgb.min) == pre_rgb.index(rgb.min) && rgb.index(rgb.max) == pre_rgb.index(pre_rgb.max)
- expect(same).not_to eq true
- end
- pre_rgb = rgb
- end
+ it 'should work with color style' do
+ res = RuCaptcha.create(1)
+ expect(res.length).to eq(2)
+ expect(res[0].length).to eq(5)
+ expect(res[1]).not_to eq(nil)
end
end
end
diff --git a/spec/configure_spec.rb b/spec/configure_spec.rb
index 90c9e50..fc5dd75 100644
--- a/spec/configure_spec.rb
+++ b/spec/configure_spec.rb
@@ -3,9 +3,6 @@ require 'spec_helper'
describe RuCaptcha do
describe 'normal' do
it 'should read right config with spec_helper set' do
- expect(RuCaptcha.config.len).to eq(2)
- expect(RuCaptcha.config.font_size).to eq(48)
- expect(RuCaptcha.config.implode).to eq(0.111)
expect(RuCaptcha.config.expires_in).to eq(2.minutes)
end
end
diff --git a/spec/controller_helpers_spec.rb b/spec/controller_helpers_spec.rb
index fd43266..995c403 100644
--- a/spec/controller_helpers_spec.rb
+++ b/spec/controller_helpers_spec.rb
@@ -37,9 +37,9 @@ describe RuCaptcha do
describe '.generate_rucaptcha' do
it 'should work' do
- expect(RuCaptcha::Captcha).to receive(:random_chars).and_return('abcd')
- expect(simple.generate_rucaptcha).not_to be_nil
- expect(simple.custom_session[:code]).to eq('abcd')
+ allow(RuCaptcha).to receive(:create).and_return(['abcde', 'fake image data'])
+ expect(simple.generate_rucaptcha).to eq 'fake image data'
+ expect(simple.custom_session[:code]).to eq('abcde')
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 0e13a35..f53d402 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -21,8 +21,5 @@ module Rails
end
RuCaptcha.configure do
- self.len = 2
- self.font_size = 48
- self.implode = 0.111
self.cache_store = :mem_cache_store
end
diff --git a/test b/test
new file mode 100755
index 0000000..39a9f4d
--- /dev/null
+++ b/test
@@ -0,0 +1,2 @@
+rake clean && rake compile > /dev/null 2& > /dev/null
+rake preview > /tmp/rucaptcha-test.gif && open /tmp/rucaptcha-test.gif
\ No newline at end of file