gamefic 3.4.0 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +1 -1
- data/lib/gamefic/active/epic.rb +1 -0
- data/lib/gamefic/active.rb +4 -0
- data/lib/gamefic/chapter.rb +25 -42
- data/lib/gamefic/command.rb +40 -1
- data/lib/gamefic/dispatcher.rb +5 -31
- data/lib/gamefic/entity.rb +26 -0
- data/lib/gamefic/narrative.rb +9 -5
- data/lib/gamefic/plot.rb +5 -0
- data/lib/gamefic/proxy.rb +46 -0
- data/lib/gamefic/query/base.rb +28 -12
- data/lib/gamefic/query/general.rb +3 -12
- data/lib/gamefic/query/result.rb +4 -1
- data/lib/gamefic/query/scoped.rb +1 -18
- data/lib/gamefic/query/text.rb +13 -12
- data/lib/gamefic/response.rb +65 -34
- data/lib/gamefic/scanner/base.rb +44 -0
- data/lib/gamefic/scanner/fuzzy.rb +17 -0
- data/lib/gamefic/scanner/fuzzy_nesting.rb +14 -0
- data/lib/gamefic/scanner/nesting.rb +39 -0
- data/lib/gamefic/scanner/result.rb +50 -0
- data/lib/gamefic/scanner/strict.rb +31 -0
- data/lib/gamefic/scanner.rb +33 -111
- data/lib/gamefic/scope/descendants.rb +16 -0
- data/lib/gamefic/scope/family.rb +31 -8
- data/lib/gamefic/scope.rb +1 -0
- data/lib/gamefic/scriptable/actions.rb +4 -23
- data/lib/gamefic/scriptable/entities.rb +4 -1
- data/lib/gamefic/scriptable/plot_proxies.rb +16 -0
- data/lib/gamefic/scriptable/proxies.rb +31 -0
- data/lib/gamefic/scriptable/queries.rb +15 -7
- data/lib/gamefic/scriptable/scenes.rb +7 -1
- data/lib/gamefic/scriptable.rb +67 -15
- data/lib/gamefic/stage.rb +2 -2
- data/lib/gamefic/subplot.rb +27 -1
- data/lib/gamefic/version.rb +1 -1
- data/lib/gamefic.rb +1 -1
- metadata +12 -4
- data/lib/gamefic/composer.rb +0 -70
- data/lib/gamefic/scriptable/proxy.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79309729d2296ceec16e10d3380fba331512f15ca2d303788c1fbcc83c077457
|
4
|
+
data.tar.gz: f4ce7d947730da4e833d895ae3085c4027d80cf89306b3aeff03d1a2a6ecd2aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01c7c68bdc217447d90bda4c2bdd362e318c644dc3486999f6125d6c124193e0b33782a250272a2455ea98e2f531551f3819611c4139b191d3dccaa61d9e03d8
|
7
|
+
data.tar.gz: '06101965d9a47188f2b5b22e87f4f7b4bbeefd5f102d2405e1457c8a389a732e782cd4eedccec2176f2b237ad3783b1ab0058ce2721e451caa29e4e8a6d52cdc'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 3.5.0
|
2
|
+
- Configurable scanners
|
3
|
+
- Refactored scanners and queries
|
4
|
+
- Allow assignment to nil instance variables in stage
|
5
|
+
- Lazy proxies
|
6
|
+
- Remove buggy index proxies
|
7
|
+
- Chapter inherits Narrative
|
8
|
+
- Plot attribute proxy for chapters and subplots
|
9
|
+
- Entity#leave
|
10
|
+
- Descendants query
|
11
|
+
- Persistent subplots
|
12
|
+
- Entity#broadcast
|
13
|
+
- Ascendants in family query
|
14
|
+
|
1
15
|
## 3.4.0 - September 10, 2024
|
2
16
|
- Chapters
|
3
17
|
- Subplots and chapters do not repeat plot scripts
|
data/README.md
CHANGED
@@ -16,7 +16,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
16
16
|
|
17
17
|
## Contributing
|
18
18
|
|
19
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/castwide/gamefic
|
19
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/castwide/gamefic.
|
20
20
|
|
21
21
|
## License
|
22
22
|
|
data/lib/gamefic/active/epic.rb
CHANGED
data/lib/gamefic/active.rb
CHANGED
data/lib/gamefic/chapter.rb
CHANGED
@@ -6,17 +6,15 @@ module Gamefic
|
|
6
6
|
# adding the required instance variables, methods, and attributes to the
|
7
7
|
# plot.
|
8
8
|
#
|
9
|
-
# Chapters are similar to subplots with
|
10
|
-
# * Chapters persist for the duration of
|
9
|
+
# Chapters are similar to subplots with three important exceptions:
|
10
|
+
# * Chapters normally persist for the duration of a plot.
|
11
11
|
# * Players do not need to be introduced to a chapter.
|
12
|
-
# *
|
13
|
-
# * Using `make` to create an entity in a chapter adds it to the parent
|
14
|
-
# plot's entity list.
|
12
|
+
# * Chapters share their plot's entities, players, and rulebook.
|
15
13
|
#
|
16
14
|
# @example
|
17
15
|
# class MyChapter < Gamefic::Chapter
|
18
|
-
#
|
19
|
-
# @thing
|
16
|
+
# def thing
|
17
|
+
# @thing ||= make Gamefic::Entity, name: 'chapter thing'
|
20
18
|
# end
|
21
19
|
# end
|
22
20
|
#
|
@@ -25,64 +23,49 @@ module Gamefic
|
|
25
23
|
# end
|
26
24
|
#
|
27
25
|
# plot = MyPlot.new
|
28
|
-
# plot.entities
|
29
|
-
# plot.
|
26
|
+
# plot.entities #=> [<#Gamefic::Entity a chapter thing>]
|
27
|
+
# plot.thing # raises NoMethodError
|
28
|
+
# plot.chapters.first.thing #=> <#Gamefic::Entity a chapter thing>
|
30
29
|
#
|
31
|
-
class Chapter
|
32
|
-
extend Scriptable
|
33
|
-
|
34
|
-
include Scriptable::Actions
|
35
|
-
include Scriptable::Events
|
36
|
-
include Scriptable::Proxy
|
37
|
-
include Scriptable::Queries
|
38
|
-
include Scriptable::Scenes
|
30
|
+
class Chapter < Narrative
|
31
|
+
extend Scriptable::PlotProxies
|
39
32
|
|
40
33
|
# @return [Plot]
|
41
34
|
attr_reader :plot
|
42
35
|
|
43
36
|
# @param plot [Plot]
|
44
|
-
def initialize
|
37
|
+
def initialize(plot)
|
45
38
|
@plot = plot
|
46
|
-
|
47
|
-
|
48
|
-
def included_blocks
|
49
|
-
self.class.included_blocks - plot.included_blocks
|
50
|
-
end
|
51
|
-
|
52
|
-
def seed
|
53
|
-
included_blocks.select(&:seed?).each { |blk| Stage.run self, &blk.code }
|
39
|
+
# The plot is responsible for hydrating chapters
|
40
|
+
super(hydrate: false)
|
54
41
|
end
|
55
42
|
|
56
43
|
def script
|
57
44
|
included_blocks.select(&:script?).each { |blk| Stage.run self, &blk.code }
|
58
45
|
end
|
59
46
|
|
60
|
-
def
|
61
|
-
plot.
|
62
|
-
end
|
63
|
-
|
64
|
-
def make klass, **opts
|
65
|
-
plot.make klass, **opts
|
47
|
+
def included_blocks
|
48
|
+
self.class.included_blocks - plot.included_blocks
|
66
49
|
end
|
67
50
|
|
68
|
-
def
|
69
|
-
plot.
|
51
|
+
def rulebook
|
52
|
+
plot.rulebook
|
70
53
|
end
|
71
54
|
|
72
|
-
def
|
73
|
-
plot.
|
55
|
+
def entity_vault
|
56
|
+
plot.entity_vault
|
74
57
|
end
|
75
58
|
|
76
|
-
def
|
77
|
-
plot.
|
59
|
+
def player_vault
|
60
|
+
plot.player_vault
|
78
61
|
end
|
79
62
|
|
80
|
-
def
|
81
|
-
plot.
|
63
|
+
def subplots
|
64
|
+
plot.subplots
|
82
65
|
end
|
83
66
|
|
84
|
-
def
|
85
|
-
plot.
|
67
|
+
def branch(...)
|
68
|
+
plot.branch(...)
|
86
69
|
end
|
87
70
|
end
|
88
71
|
end
|
data/lib/gamefic/command.rb
CHANGED
@@ -10,11 +10,50 @@ module Gamefic
|
|
10
10
|
# @return [Array<Array<Entity>, Entity, String>]
|
11
11
|
attr_reader :arguments
|
12
12
|
|
13
|
+
# @return [Integer]
|
14
|
+
attr_reader :strictness
|
15
|
+
|
16
|
+
# @return [Integer]
|
17
|
+
attr_reader :precision
|
18
|
+
|
13
19
|
# @param verb [Symbol]
|
14
20
|
# @param arguments [Array<Array<Entity>, Entity, String>]
|
15
|
-
|
21
|
+
# @param strictness [Integer]
|
22
|
+
# @param precision [Integer]
|
23
|
+
#
|
24
|
+
# @todo Consider making strictness and precision required or providing
|
25
|
+
# another generator
|
26
|
+
def initialize verb, arguments, strictness = 0, precision = 0
|
16
27
|
@verb = verb
|
17
28
|
@arguments = arguments
|
29
|
+
@strictness = strictness
|
30
|
+
@precision = precision
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
# Compose a command from input.
|
35
|
+
#
|
36
|
+
# @param actor [Actor]
|
37
|
+
# @param input [String]
|
38
|
+
# @return [Command]
|
39
|
+
def compose actor, input
|
40
|
+
expressions = Syntax.tokenize(input, actor.epic.syntaxes)
|
41
|
+
expressions.flat_map { |expression| expression_to_commands(actor, expression) }
|
42
|
+
.first || Command.new(nil, [])
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# @param actor [Actor]
|
48
|
+
# @param expression [Expression]
|
49
|
+
# @return [Array<Command>]
|
50
|
+
def expression_to_commands actor, expression
|
51
|
+
actor.epic
|
52
|
+
.responses_for(expression.verb)
|
53
|
+
.map { |response| response.to_command(actor, expression) }
|
54
|
+
.compact
|
55
|
+
.sort_by.with_index { |result, idx| [-result.precision, -result.strictness, idx] }
|
56
|
+
end
|
18
57
|
end
|
19
58
|
end
|
20
59
|
end
|
data/lib/gamefic/dispatcher.rb
CHANGED
@@ -10,7 +10,6 @@ module Gamefic
|
|
10
10
|
@actor = actor
|
11
11
|
@command = command
|
12
12
|
@executed = false
|
13
|
-
@finalized = false
|
14
13
|
end
|
15
14
|
|
16
15
|
# Run the dispatcher.
|
@@ -23,11 +22,11 @@ module Gamefic
|
|
23
22
|
action = next_action
|
24
23
|
return unless action
|
25
24
|
|
26
|
-
|
25
|
+
actor.epic.rulebooks.flat_map { |rlbk| rlbk.run_before_actions action }
|
27
26
|
return if action.cancelled?
|
28
27
|
|
29
28
|
action.execute
|
30
|
-
|
29
|
+
actor.epic.rulebooks.flat_map { |rlbk| rlbk.run_after_actions action }
|
31
30
|
action
|
32
31
|
end
|
33
32
|
|
@@ -46,9 +45,9 @@ module Gamefic
|
|
46
45
|
# @param input [String]
|
47
46
|
# @return [Dispatcher]
|
48
47
|
def self.dispatch actor, input
|
49
|
-
expressions = Syntax.tokenize(input, actor.epic.syntaxes)
|
50
|
-
|
51
|
-
new(actor,
|
48
|
+
# expressions = Syntax.tokenize(input, actor.epic.syntaxes)
|
49
|
+
# new(actor, Command.compose(actor, expressions))
|
50
|
+
new(actor, Command.compose(actor, input))
|
52
51
|
end
|
53
52
|
|
54
53
|
# @param actor [Active]
|
@@ -82,31 +81,6 @@ module Gamefic
|
|
82
81
|
|
83
82
|
return Action.new(actor, @command.arguments, response) if response.accept?(actor, @command)
|
84
83
|
end
|
85
|
-
finalize
|
86
|
-
end
|
87
|
-
|
88
|
-
# @return [void]
|
89
|
-
def run_before_action_hooks action
|
90
|
-
actor.epic.rulebooks.flat_map { |rlbk| rlbk.run_before_actions action }
|
91
|
-
end
|
92
|
-
|
93
|
-
# @return [void]
|
94
|
-
def run_after_action_hooks action
|
95
|
-
actor.epic.rulebooks.flat_map { |rlbk| rlbk.run_after_actions action }
|
96
|
-
end
|
97
|
-
|
98
|
-
# If the dispatcher proceeds through all possible responses, it can fall
|
99
|
-
# back to a nil response as a catchall for commands that could not be
|
100
|
-
# completed.
|
101
|
-
#
|
102
|
-
# @return [Action, nil]
|
103
|
-
def finalize
|
104
|
-
return nil if @finalized
|
105
|
-
|
106
|
-
@finalized = true
|
107
|
-
@command = Command.new(nil, ["#{command.verb} #{command.arguments.join(' ').strip}"])
|
108
|
-
@responses = actor.epic.responses_for(nil)
|
109
|
-
next_action
|
110
84
|
end
|
111
85
|
end
|
112
86
|
end
|
data/lib/gamefic/entity.rb
CHANGED
@@ -55,6 +55,32 @@ module Gamefic
|
|
55
55
|
"#<#{self.class} #{name}>"
|
56
56
|
end
|
57
57
|
|
58
|
+
# Move this entity to its parent entity.
|
59
|
+
#
|
60
|
+
# @example
|
61
|
+
# room = Gamefic::Entity.new(name: 'room')
|
62
|
+
# person = Gamefic::Entity.new(name: 'person', parent: room)
|
63
|
+
# thing = Gamefic::Entity.new(name: 'thing', parent: person)
|
64
|
+
#
|
65
|
+
# thing.parent #=> person
|
66
|
+
# thing.leave
|
67
|
+
# thing.parent #=> room
|
68
|
+
#
|
69
|
+
# @return [void]
|
70
|
+
def leave
|
71
|
+
self.parent = parent&.parent
|
72
|
+
end
|
73
|
+
|
74
|
+
# Tell a message to all of this entity's accessible descendants.
|
75
|
+
#
|
76
|
+
# @param message [String]
|
77
|
+
# @return [void]
|
78
|
+
def broadcast message
|
79
|
+
Query::Scoped.new(Scope::Descendants).select(self)
|
80
|
+
.that_are(Active, proc(&:acting?))
|
81
|
+
.each { |actor| actor.tell message }
|
82
|
+
end
|
83
|
+
|
58
84
|
class << self
|
59
85
|
# Set or update the default attributes for new instances.
|
60
86
|
#
|
data/lib/gamefic/narrative.rb
CHANGED
@@ -14,16 +14,18 @@ module Gamefic
|
|
14
14
|
include Scriptable::Actions
|
15
15
|
include Scriptable::Entities
|
16
16
|
include Scriptable::Events
|
17
|
-
include Scriptable::
|
17
|
+
include Scriptable::Proxies
|
18
18
|
include Scriptable::Queries
|
19
19
|
include Scriptable::Scenes
|
20
20
|
|
21
21
|
attr_reader :rulebook
|
22
22
|
|
23
|
-
def initialize
|
23
|
+
def initialize(hydrate: true)
|
24
|
+
return unless hydrate
|
25
|
+
|
24
26
|
seed
|
25
27
|
script
|
26
|
-
|
28
|
+
post_script
|
27
29
|
end
|
28
30
|
|
29
31
|
def seed
|
@@ -35,15 +37,17 @@ module Gamefic
|
|
35
37
|
included_blocks.select(&:script?).each { |blk| Stage.run self, &blk.code }
|
36
38
|
end
|
37
39
|
|
40
|
+
# @return [Array<Module>]
|
38
41
|
def included_blocks
|
39
42
|
self.class.included_blocks
|
40
43
|
end
|
41
44
|
|
42
|
-
def
|
45
|
+
def post_script
|
43
46
|
entity_vault.lock
|
44
47
|
rulebook.freeze
|
45
48
|
end
|
46
49
|
|
50
|
+
# @return [Array<Symbol>]
|
47
51
|
def scenes
|
48
52
|
rulebook.scenes.names
|
49
53
|
end
|
@@ -111,7 +115,7 @@ module Gamefic
|
|
111
115
|
|
112
116
|
def hydrate
|
113
117
|
script
|
114
|
-
|
118
|
+
post_script
|
115
119
|
end
|
116
120
|
|
117
121
|
def self.inherited klass
|
data/lib/gamefic/plot.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gamefic
|
4
|
+
class Proxy
|
5
|
+
# @return [Symbol]
|
6
|
+
attr_reader :type
|
7
|
+
|
8
|
+
# @return [Symbol, Array<Symbol>, String, Integer]
|
9
|
+
attr_reader :key
|
10
|
+
|
11
|
+
# @param type [Symbol]
|
12
|
+
# @param key [Symbol, String]
|
13
|
+
def initialize type, key
|
14
|
+
@type = type
|
15
|
+
@key = key
|
16
|
+
validate_type
|
17
|
+
end
|
18
|
+
|
19
|
+
def fetch narrative
|
20
|
+
send(type, narrative) ||
|
21
|
+
raise(ArgumentError, "Unable to fetch entity from proxy agent symbol `#{key}`")
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def attr narrative
|
27
|
+
Stage.run(narrative, [key].flatten) { |keys| keys.inject(self) { |obj, key| obj.send key } }
|
28
|
+
rescue NoMethodError
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def ivar narrative
|
33
|
+
narrative.instance_variable_get key
|
34
|
+
end
|
35
|
+
|
36
|
+
def pick narrative
|
37
|
+
narrative.pick! key
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_type
|
41
|
+
return if [:attr, :ivar, :pick].include?(type)
|
42
|
+
|
43
|
+
raise ArgumentError, "Invalid proxy type `#{type}` (must be :attr, :ivar, or :pick)"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/gamefic/query/base.rb
CHANGED
@@ -13,6 +13,8 @@ module Gamefic
|
|
13
13
|
# @return [Boolean]
|
14
14
|
attr_reader :ambiguous
|
15
15
|
|
16
|
+
attr_accessor :narrative
|
17
|
+
|
16
18
|
# @raise [ArgumentError] if any of the arguments are nil
|
17
19
|
#
|
18
20
|
# @param arguments [Array<Object>]
|
@@ -26,12 +28,6 @@ module Gamefic
|
|
26
28
|
|
27
29
|
# Get a query result for a given subject and token.
|
28
30
|
#
|
29
|
-
# @note This method is retained as a convenience for authors. Narratives
|
30
|
-
# should use Composer to build commands, as it provides more precise
|
31
|
-
# matching of tokens to valid response arguments. Authors can use
|
32
|
-
# #query to find entities that match a token regardless of whether the
|
33
|
-
# result matches an available response.
|
34
|
-
#
|
35
31
|
# @example
|
36
32
|
# respond :reds do |actor|
|
37
33
|
# reds = available(ambiguous: true).query(actor, 'red').match
|
@@ -41,19 +37,28 @@ module Gamefic
|
|
41
37
|
# @param subject [Gamefic::Entity]
|
42
38
|
# @param token [String]
|
43
39
|
# @return [Result]
|
44
|
-
def query(
|
45
|
-
|
40
|
+
def query(subject, token)
|
41
|
+
scan = Scanner.scan(select(subject), token)
|
42
|
+
ambiguous? ? ambiguous_result(scan) : unambiguous_result(scan)
|
46
43
|
end
|
44
|
+
alias filter query
|
47
45
|
|
48
46
|
# Get an array of entities that match the query from the context of the
|
49
47
|
# subject.
|
50
48
|
#
|
49
|
+
# Subclasses should override this method.
|
50
|
+
#
|
51
51
|
# @param subject [Entity]
|
52
52
|
# @return [Array<Entity>]
|
53
53
|
def select _subject
|
54
|
-
|
54
|
+
[]
|
55
55
|
end
|
56
56
|
|
57
|
+
# True if the object is selectable by the subject.
|
58
|
+
#
|
59
|
+
# @param subject [Entity]
|
60
|
+
# @param object [Array<Entity>, Entity]
|
61
|
+
# @return [Boolean]
|
57
62
|
def accept?(subject, object)
|
58
63
|
available = select(subject)
|
59
64
|
if ambiguous?
|
@@ -75,9 +80,9 @@ module Gamefic
|
|
75
80
|
private
|
76
81
|
|
77
82
|
def calculate_precision
|
78
|
-
|
83
|
+
unproxied_arguments.sum(@ambiguous ? -1000 : 0) do |arg|
|
79
84
|
case arg
|
80
|
-
when Entity,
|
85
|
+
when Entity, Proxy
|
81
86
|
1000
|
82
87
|
when Class, Module
|
83
88
|
class_depth(arg) * 100
|
@@ -107,7 +112,18 @@ module Gamefic
|
|
107
112
|
def unambiguous_result scan
|
108
113
|
return Result.new(nil, scan.token) unless scan.matched.one?
|
109
114
|
|
110
|
-
Result.new(scan.matched.first, scan.remainder)
|
115
|
+
Result.new(scan.matched.first, scan.remainder, scan.strictness)
|
116
|
+
end
|
117
|
+
|
118
|
+
def unproxied_arguments
|
119
|
+
@unproxied_arguments ||= arguments.map do |arg|
|
120
|
+
case arg
|
121
|
+
when Proxy
|
122
|
+
arg.fetch(narrative)
|
123
|
+
else
|
124
|
+
arg
|
125
|
+
end
|
126
|
+
end
|
111
127
|
end
|
112
128
|
end
|
113
129
|
end
|
@@ -20,16 +20,7 @@ module Gamefic
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def select subject
|
23
|
-
available_entities(subject).that_are(
|
24
|
-
end
|
25
|
-
|
26
|
-
def query subject, token
|
27
|
-
filtered = available_entities(subject).that_are(*@arguments)
|
28
|
-
return Result.new(token, nil) if filtered.include?(token)
|
29
|
-
|
30
|
-
scan = Scanner.scan(filtered, token)
|
31
|
-
|
32
|
-
ambiguous? ? ambiguous_result(scan) : unambiguous_result(scan)
|
23
|
+
available_entities(subject).that_are(*unproxied_arguments)
|
33
24
|
end
|
34
25
|
|
35
26
|
private
|
@@ -37,9 +28,9 @@ module Gamefic
|
|
37
28
|
def available_entities(subject)
|
38
29
|
if @entities.is_a?(Proc)
|
39
30
|
if @entities.arity.zero?
|
40
|
-
|
31
|
+
Stage.run narrative, &@entities
|
41
32
|
else
|
42
|
-
|
33
|
+
Stage.run narrative, subject, &@entities
|
43
34
|
end
|
44
35
|
else
|
45
36
|
@entities
|
data/lib/gamefic/query/result.rb
CHANGED
@@ -11,9 +11,12 @@ module Gamefic
|
|
11
11
|
# @return [String]
|
12
12
|
attr_reader :remainder
|
13
13
|
|
14
|
-
|
14
|
+
attr_reader :strictness
|
15
|
+
|
16
|
+
def initialize match, remainder, strictness = 0
|
15
17
|
@match = match
|
16
18
|
@remainder = remainder
|
19
|
+
@strictness = strictness
|
17
20
|
end
|
18
21
|
end
|
19
22
|
end
|
data/lib/gamefic/query/scoped.rb
CHANGED
@@ -17,29 +17,12 @@ module Gamefic
|
|
17
17
|
|
18
18
|
def select(subject)
|
19
19
|
@scope.matches(subject)
|
20
|
-
.that_are(
|
21
|
-
end
|
22
|
-
|
23
|
-
# @return [Result]
|
24
|
-
def query(subject, token)
|
25
|
-
available = @scope.matches(subject)
|
26
|
-
.that_are(*@arguments)
|
27
|
-
return Result.new(token, nil) if available.include?(token)
|
28
|
-
|
29
|
-
scan = Scanner.scan(available, token)
|
30
|
-
|
31
|
-
return ambiguous_result(scan) if ambiguous?
|
32
|
-
|
33
|
-
unambiguous_result(scan)
|
20
|
+
.that_are(*unproxied_arguments)
|
34
21
|
end
|
35
22
|
|
36
23
|
def precision
|
37
24
|
@precision ||= @scope.precision + calculate_precision
|
38
25
|
end
|
39
|
-
|
40
|
-
def ambiguous?
|
41
|
-
@ambiguous
|
42
|
-
end
|
43
26
|
end
|
44
27
|
end
|
45
28
|
end
|
data/lib/gamefic/query/text.rb
CHANGED
@@ -4,16 +4,20 @@ module Gamefic
|
|
4
4
|
module Query
|
5
5
|
# A special query that handles text instead of entities.
|
6
6
|
#
|
7
|
-
class Text
|
7
|
+
class Text < Base
|
8
8
|
# @param argument [String, Regexp]
|
9
9
|
def initialize argument = /.*/
|
10
|
-
|
10
|
+
super
|
11
11
|
validate
|
12
12
|
end
|
13
13
|
|
14
|
+
def argument
|
15
|
+
arguments.first
|
16
|
+
end
|
17
|
+
|
14
18
|
# @return [String, Regexp]
|
15
19
|
def select(_subject)
|
16
|
-
|
20
|
+
argument
|
17
21
|
end
|
18
22
|
|
19
23
|
def query _subject, token
|
@@ -23,6 +27,7 @@ module Gamefic
|
|
23
27
|
Result.new(nil, token)
|
24
28
|
end
|
25
29
|
end
|
30
|
+
alias filter query
|
26
31
|
|
27
32
|
def precision
|
28
33
|
0
|
@@ -32,25 +37,21 @@ module Gamefic
|
|
32
37
|
match? argument
|
33
38
|
end
|
34
39
|
|
35
|
-
def ambiguous?
|
36
|
-
true
|
37
|
-
end
|
38
|
-
|
39
40
|
private
|
40
41
|
|
41
42
|
def match? token
|
42
|
-
return false unless token.is_a?(String)
|
43
|
+
return false unless token.is_a?(String) && !token.empty?
|
43
44
|
|
44
|
-
case
|
45
|
+
case argument
|
45
46
|
when Regexp
|
46
|
-
token =~
|
47
|
+
token =~ argument
|
47
48
|
else
|
48
|
-
token ==
|
49
|
+
token == argument
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
52
53
|
def validate
|
53
|
-
return if
|
54
|
+
return if argument.is_a?(String) || argument.is_a?(Regexp)
|
54
55
|
|
55
56
|
raise ArgumentError, 'Invalid text query argument'
|
56
57
|
end
|