gamefic 3.4.0 → 3.5.0
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.
- 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
|