auser-aska 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG ADDED
@@ -0,0 +1,2 @@
1
+ v0.0.2 Added buckets of rules
2
+ v0.0.1 First write
data/LICENSE ADDED
File without changes
data/README ADDED
@@ -0,0 +1,60 @@
1
+ = AskA
2
+ Ari Lerner
3
+ CitrusByte
4
+ http://blog.citrusbyte.com
5
+
6
+ == DESCRIPTION:
7
+
8
+ * Super basic rule-based parser to match given rules
9
+
10
+ == Basics
11
+
12
+ In your class, add your rule definitions
13
+
14
+ class Car
15
+ include Aska
16
+ attr_accessor :x, :y
17
+ rules :names, <<-EOR
18
+ x > 0
19
+ x > y
20
+ y > 0
21
+ EOR
22
+ end
23
+
24
+ Then you can see if the rules are matched with the call
25
+
26
+ @car.rules_valid?(:names)
27
+
28
+ If they do all match, then the rules_valid? will return true, otherwise it will return false
29
+
30
+ == INSTALL:
31
+
32
+ gem install aska
33
+
34
+ == ROADMAP
35
+ * v0.0.1 - First release
36
+
37
+ == LICENSE:
38
+
39
+ (The MIT License)
40
+
41
+ Copyright (c) 2008 Ari Lerner. CitrusByte
42
+
43
+ Permission is hereby granted, free of charge, to any person obtaining
44
+ a copy of this software and associated documentation files (the
45
+ 'Software'), to deal in the Software without restriction, including
46
+ without limitation the rights to use, copy, modify, merge, publish,
47
+ distribute, sublicense, and/or sell copies of the Software, and to
48
+ permit persons to whom the Software is furnished to do so, subject to
49
+ the following conditions:
50
+
51
+ The above copyright notice and this permission notice shall be
52
+ included in all copies or substantial portions of the Software.
53
+
54
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
55
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
56
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
57
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
58
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
59
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
60
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,69 @@
1
+ begin
2
+ require 'echoe'
3
+ Echoe.new("aska") do |p|
4
+ p.author = "Ari Lerner"
5
+ p.email = "ari.lerner@citrusbyte.com"
6
+ p.summary = "The basics of an expert system"
7
+ p.url = "http://blog.citrusbyte.com"
8
+ p.dependencies = []
9
+ p.install_message =<<-EOM
10
+
11
+ Aska - Expert system basics
12
+ *** Ari Lerner @ <ari.lerner@citrusbyte.com> ***
13
+
14
+ EOM
15
+ p.include_rakefile = true
16
+ end
17
+ rescue Exception => e
18
+
19
+ end
20
+
21
+ namespace(:pkg) do
22
+ ## Rake task to create/update a .manifest file in your project, as well as update *.gemspec
23
+ desc %{Update ".manifest" with the latest list of project filenames. Respect\
24
+ .gitignore by excluding everything that git ignores. Update `files` and\
25
+ `test_files` arrays in "*.gemspec" file if it's present.}
26
+ task :manifest do
27
+ list = Dir['**/*'].sort
28
+ spec_file = Dir['*.gemspec'].first
29
+ list -= [spec_file] if spec_file
30
+
31
+ File.read('.gitignore').each_line do |glob|
32
+ glob = glob.chomp.sub(/^\//, '')
33
+ list -= Dir[glob]
34
+ list -= Dir["#{glob}/**/*"] if File.directory?(glob) and !File.symlink?(glob)
35
+ puts "excluding #{glob}"
36
+ end
37
+
38
+ if spec_file
39
+ spec = File.read spec_file
40
+ spec.gsub! /^(\s* s.(test_)?files \s* = \s* )( \[ [^\]]* \] | %w\( [^)]* \) )/mx do
41
+ assignment = $1
42
+ bunch = $2 ? list.grep(/^test\//) : list
43
+ '%s%%w(%s)' % [assignment, bunch.join(' ')]
44
+ end
45
+
46
+ File.open(spec_file, 'w') {|f| f << spec }
47
+ end
48
+ File.open('Manifest', 'w') {|f| f << list.join("\n") }
49
+ end
50
+ desc "Build gemspec for github"
51
+ task :gemspec => :manifest do
52
+ require "yaml"
53
+ `rake manifest gem`
54
+ data = YAML.load(open("aska.gemspec").read).to_ruby
55
+ File.open("aska.gemspec", "w+") {|f| f << data }
56
+ end
57
+ desc "Update gemspec with the time"
58
+ task :gemspec_update => :gemspec do
59
+ end
60
+ desc "Get ready to release the gem"
61
+ task :prerelease => :gemspec_update do
62
+ `git add .`
63
+ `git ci -a -m "Updated gemspec for github"`
64
+ end
65
+ desc "Release them gem to the gem server"
66
+ task :release => :prerelease do
67
+ `git push origin master`
68
+ end
69
+ end
data/aska.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{aska}
3
+ s.version = "0.0.2"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new("= 1.2") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Ari Lerner"]
7
+ s.cert_chain = nil
8
+ s.date = %q{2008-07-01}
9
+ s.description = %q{The basics of an expert system}
10
+ s.email = %q{ari.lerner@citrusbyte.com}
11
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "lib", "lib/aska", "lib/aska.rb"]
12
+ s.files = ["CHANGELOG", "LICENSE", "README", "Rakefile", "lib", "lib/aska", "lib/aska.rb", "pkg", "spec", "spec/rules_spec.rb", "spec/spec_helper.rb", "aska.gemspec"]
13
+ s.has_rdoc = true
14
+ s.homepage = %q{http://blog.citrusbyte.com}
15
+ s.post_install_message = %q{
16
+ Aska - Expert system basics
17
+ *** Ari Lerner @ <ari.lerner@citrusbyte.com> ***
18
+
19
+ }
20
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Aska", "--main", "README"]
21
+ s.require_paths = ["lib"]
22
+ s.rubyforge_project = %q{aska}
23
+ s.rubygems_version = %q{1.2.0}
24
+ s.summary = %q{The basics of an expert system}
25
+
26
+ if s.respond_to? :specification_version then
27
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
28
+ s.specification_version = 2
29
+
30
+ if current_version >= 3 then
31
+ s.add_development_dependency(%q<echoe>, [">= 0"])
32
+ else
33
+ s.add_dependency(%q<echoe>, [">= 0"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<echoe>, [">= 0"])
37
+ end
38
+ end
data/lib/aska.rb ADDED
@@ -0,0 +1,83 @@
1
+ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
2
+
3
+ Dir["aska/**"].each {|a| require a }
4
+
5
+ module Aska
6
+ module ClassMethods
7
+ def rules(name=:rules, str="")
8
+ r = look_up_rules(name)
9
+ str.each_line do |line|
10
+ k = line[/(.+)[=\\\<\>](.*)/, 1].gsub(/\s+/, '')
11
+ v = line[/(.+)[=\\<>](.*)/, 2].gsub(/\s+/, '')
12
+ m = line[/[=\\<>]/, 0].gsub(/\s+/, '')
13
+
14
+ create_instance_variable(k)
15
+ r << {k => [m, v]}
16
+ end
17
+ end
18
+ def create_instance_variable(name)
19
+ return unless name
20
+ attr_accessors << name.to_sym
21
+ eval "attr_accessor :#{name}"
22
+ end
23
+ def look_up_rules(name)
24
+ defined_rules["#{name}"] ||= []
25
+ end
26
+ def attr_accessors
27
+ @attr_accessors ||= []
28
+ end
29
+ def defined_rules
30
+ @defined_rules ||= {}
31
+ end
32
+ end
33
+
34
+ module InstanceMethods
35
+ def rules
36
+ @rules ||= self.class.defined_rules
37
+ end
38
+ def valid_rules?(name=:rules)
39
+ arr = self.class.look_up_rules(name).collect do |rule|
40
+ valid_rule?(rule)
41
+ end
42
+ arr.reject {|a| a == true }.empty?
43
+ end
44
+ def valid_rule?(rule)
45
+ return false unless rule # Can't apply a rule that is nil, can we?
46
+ rule.each do |key,value|
47
+ begin
48
+ # puts "testing if #{key} (#{self.send(key)}) is #{value[0]} #{get_var(value[1])} [#{value[1]}]"
49
+ return self.send(key).send(value[0].to_sym, get_var(value[1]))
50
+ rescue Exception => e
51
+ return false
52
+ end
53
+ end
54
+ end
55
+ # Get the variable from the class
56
+ # If it's defined as an attr_accessor, we know it has been defined as a rule
57
+ # Otherwise, if we are passing it as a
58
+ def get_var(name)
59
+ attr_accessor?(name) ? self.send(name.to_sym) : (supported_method?(name) ? name.to_sym : name.to_f)
60
+ end
61
+ def attr_accessor?(name)
62
+ self.class.attr_accessors.include?(name.to_sym)
63
+ end
64
+ def supported_method?(meth)
65
+ %w(< > == => =<).include?("#{meth}")
66
+ end
67
+ def method_missing(m, *args)
68
+ if self.class.defined_rules.has_key?("#{m}")
69
+ self.class.send(:define_method, m) do
70
+ self.class.look_up_rules(m)
71
+ end
72
+ self.send m
73
+ else
74
+ super
75
+ end
76
+ end
77
+ end
78
+
79
+ def self.included(receiver)
80
+ receiver.extend ClassMethods
81
+ receiver.send :include, InstanceMethods
82
+ end
83
+ end
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class Car
4
+ include Aska
5
+ rules :names, <<-EOR
6
+ x > 0
7
+ y > 0
8
+ x > y
9
+ EOR
10
+ end
11
+ describe "Rules" do
12
+ before(:each) do
13
+ @car = Car.new
14
+ end
15
+ it "should be able to define rules as an array and they should be set as the rules on the class" do
16
+ @car.rules.class.should == Hash
17
+ end
18
+ it "should be able to look up the rules based on the name into an array" do
19
+ @car.names.class.should == Array
20
+ end
21
+ describe "parsing" do
22
+ it "should be able to parse the x > 0 into an array" do
23
+ @car.names.include?({"x"=>[">","0"]}).should == true
24
+ end
25
+ it "should be able to parse y > 0 into an array" do
26
+ @car.names.include?({"y"=>[">","0"]}).should == true
27
+ end
28
+ it "should be able to parse x > y into the hash" do
29
+ @car.names.include?({"x"=>[">","y"]}).should == true
30
+ end
31
+ it "should have 3 rules" do
32
+ @car.names.size.should == 3
33
+ end
34
+ it "should be able to look up the names as a rule" do
35
+ Car.look_up_rules(:names).should == [{"x"=>[">", "0"]}, {"y"=>[">", "0"]}, {"x"=>[">", "y"]}]
36
+ end
37
+ end
38
+ it "should be able to get the variable associated with the instance and return it" do
39
+ @car.x = 4
40
+ @car.get_var(:x).class.should == @car.x.class
41
+ end
42
+ it "should be able to get a number with the instance and return it as a float" do
43
+ @car.get_var(4).class.should == Float
44
+ end
45
+ it "should be able to get the method it's applying as a method symbol" do
46
+ @car.get_var(:<).class.should == Symbol
47
+ end
48
+ it "should be able to retrieve the value of the rule when checking if it's valid" do
49
+ @car.x = 10
50
+ @car.valid_rule?({:x => [:==, 10]}).should == true
51
+ end
52
+ it "should be able to apply the rules and say that they are not met when they aren't" do
53
+ @car.valid_rules?(:names).should == false
54
+ end
55
+ it "should be able to apply the rules and say they aren't valid when they aren't all met" do
56
+ @car.x = 5
57
+ @car.y = 10
58
+ @car.valid_rules?(:names).should == false
59
+ end
60
+ it "should be able to apply the rules and say they aren't valid when they aren't all met" do
61
+ @car.x = 5
62
+ @car.y = 0
63
+ @car.valid_rules?(:names).should == false
64
+ end
65
+ it "should be able to apply the rules and say that they are in fact valid" do
66
+ @car.x = 10
67
+ @car.y = 5
68
+ @car.valid_rules?(:names).should == true
69
+ end
70
+ end
@@ -0,0 +1,11 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. lib aska])
2
+
3
+ %w(test/spec).each do |library|
4
+ begin
5
+ require library
6
+ rescue
7
+ STDERR.puts "== Cannot run test without #{library}"
8
+ end
9
+ end
10
+
11
+ Dir["#{File.dirname(__FILE__)}/helpers/**"].each {|a| require a}
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: auser-aska
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Ari Lerner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ date: 2008-07-01 00:00:00 -07:00
12
+ default_executable:
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: echoe
16
+ version_requirement:
17
+ version_requirements: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: "0"
22
+ version:
23
+ description: The basics of an expert system
24
+ email: ari.lerner@citrusbyte.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files:
30
+ - CHANGELOG
31
+ - LICENSE
32
+ - README
33
+ - lib
34
+ - lib/aska
35
+ - lib/aska.rb
36
+ files:
37
+ - CHANGELOG
38
+ - LICENSE
39
+ - README
40
+ - Rakefile
41
+ - lib
42
+ - lib/aska
43
+ - lib/aska.rb
44
+ - pkg
45
+ - spec
46
+ - spec/rules_spec.rb
47
+ - spec/spec_helper.rb
48
+ - aska.gemspec
49
+ has_rdoc: true
50
+ homepage: http://blog.citrusbyte.com
51
+ post_install_message: |+
52
+
53
+ Aska - Expert system basics
54
+ *** Ari Lerner @ <ari.lerner@citrusbyte.com> ***
55
+
56
+ rdoc_options:
57
+ - --line-numbers
58
+ - --inline-source
59
+ - --title
60
+ - Aska
61
+ - --main
62
+ - README
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "="
74
+ - !ruby/object:Gem::Version
75
+ version: "1.2"
76
+ version:
77
+ requirements: []
78
+
79
+ rubyforge_project: aska
80
+ rubygems_version: 1.2.0
81
+ signing_key:
82
+ specification_version: 2
83
+ summary: The basics of an expert system
84
+ test_files: []
85
+