Class: Fable::InkList
- Inherits:
-
Object
- Object
- Fable::InkList
- Defined in:
- lib/fable/ink_list.rb
Overview
The InkList is the underlying type that’s used to store an instance of a list in ink. It’s not used for the definition of the list, but for a list value that’s stored in a variable.
Defined Under Namespace
Classes: InkListItem
Instance Attribute Summary collapse
-
#list ⇒ Object
Returns the value of attribute list.
-
#origins ⇒ Object
Returns the value of attribute origins.
Class Method Summary collapse
- .copy_list(other_list) ⇒ Object
-
.from_string(my_list_item, origin_story) ⇒ Object
Converts a string to an ink list, and returns for use in the Story.
-
.new_for_origin_definition_and_story(single_origin_list_name, origin_story) ⇒ Object
Create a new empty ink list that’s intended to hold items from a particular origin list definition.
- .new_with_single_item(item, value) ⇒ Object
Instance Method Summary collapse
-
#&(other_list) ⇒ Object
Return a new list that is the intersection of the current list and one that’s passed in.
-
#+(other_list) ⇒ Object
Return a new list that is a combination of the current list and one that’s passed in.
-
#-(other_list) ⇒ Object
Returns a new list that’s the same as the current one, except with the given items removed that are in the passed-in list.
-
#<(other_list) ⇒ Object
Returns true if all the item values in the current list are less than all the item values in the passed-in list.
-
#<=(other_list) ⇒ Object
Returns true if the item values in the current list overlap, or are all less than the item values in the passed in list.
-
#==(other_list) ⇒ Object
Returns true if the passed object is also an ink list that contains the same items as the current list, false otherwise.
-
#>(other_list) ⇒ Object
Returns true if all the item values in the current list are greater than all the item values in the passed-in list.
-
#>=(other_list) ⇒ Object
Returns true if the item values in the current list overlap, or are all greater than the item values in the passed-in list.
-
#add_ink_list_item(item) ⇒ Object
Adds the given item to the ink list.
- #add_item(item_or_item_name) ⇒ Object
-
#add_item_from_string(item_name) ⇒ Object
Adds the given item to the ink list, attempting to find the origin list definition that it belongs to.
-
#all ⇒ Object
The list of all items from the original list definition, equivalent to calling LIST_ALL(list) in ink.
-
#contains?(other_list) ⇒ Boolean
Returns true if the current list contains all the items that are in the list that is passed in.
- #count ⇒ Object
- #include_item_named?(item_name) ⇒ Boolean
-
#initialize ⇒ InkList
constructor
Create a new empty ink list.
-
#inverse ⇒ Object
The inverse of the list, equivalent to colling LIST_INVERSE(list) in ink.
- #item_with_value(value) ⇒ Object
-
#list_with_subrange(min_bound, max_bound) ⇒ Object
Returns a sublist with the elements given in the minimum & maximum bounds.
- #max_as_list ⇒ Object
-
#max_item ⇒ Object
Get the maximum item in the list, equivalent to calling LIST_MAX(list) in ink.
- #min_as_list ⇒ Object
-
#min_item ⇒ Object
Get the minimum item in the list, equivalent to calling LIST_MIN(list) in ink.
- #ordered_items ⇒ Object
-
#origin_names ⇒ Object
Origin name needs to be serialized when content is empty, assuming a name is available, for list definitions with variable that is currently empty.
-
#origin_of_max_item ⇒ Object
Story has to set this so that the value knows its origin, necessary for certain operations (eg: iteracting with ints).
- #set_initial_origin_name(initial_origin_name) ⇒ Object
- #set_initial_origin_names(initial_origin_names) ⇒ Object
-
#to_s ⇒ Object
Returns a string in the form “a, b, c” with the names of the items in the list, without the origin list definition names.
Constructor Details
#initialize ⇒ InkList
Create a new empty ink list
59 60 61 62 |
# File 'lib/fable/ink_list.rb', line 59 def initialize self.list = {} self.origins = [] end |
Instance Attribute Details
#list ⇒ Object
Returns the value of attribute list.
56 57 58 |
# File 'lib/fable/ink_list.rb', line 56 def list @list end |
#origins ⇒ Object
Returns the value of attribute origins.
56 57 58 |
# File 'lib/fable/ink_list.rb', line 56 def origins @origins end |
Class Method Details
.copy_list(other_list) ⇒ Object
64 65 66 67 68 69 70 71 72 |
# File 'lib/fable/ink_list.rb', line 64 def self.copy_list(other_list) ink_list = self.new other_list_data = other_list.list.map{|item, int_value| [InkList::InkListItem.new(full_name: item.full_name), int_value] } ink_list.list = Hash[other_list_data] ink_list.origins = other_list.origins ink_list.set_initial_origin_names(other_list.origin_names) return ink_list end |
.from_string(my_list_item, origin_story) ⇒ Object
Converts a string to an ink list, and returns for use in the Story
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/fable/ink_list.rb', line 99 def self.from_string(my_list_item, origin_story) list_value = origin_story.list_definitions[my_list_item] if list_value.nil? raise Error("Could not find the InkListItem from the string '#{my_list_item}' to create an InkList because it doesn't exist in the original list definition in ink.") else ink_list = self.new ink_list.list = list_value end return ink_list end |
.new_for_origin_definition_and_story(single_origin_list_name, origin_story) ⇒ Object
Create a new empty ink list that’s intended to hold items from a particular origin list definition. The origin story is needed in order to be able to look up that definition
84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/fable/ink_list.rb', line 84 def self.new_for_origin_definition_and_story(single_origin_list_name, origin_story) ink_list = self.new ink_list.set_initial_origin_name(single_origin_list_name) list_definition = origin_story.list_definitions.find_list(single_origin_list_name) if list_definition.nil? raise Error("InkList origin could not be found in story when constructing new list: #{single_origin_list_name}") else ink_list.origins = [list_definition] end return ink_list end |
.new_with_single_item(item, value) ⇒ Object
74 75 76 77 78 79 |
# File 'lib/fable/ink_list.rb', line 74 def self.new_with_single_item(item, value) ink_list = self.new ink_list.list[item] = value return ink_list end |
Instance Method Details
#&(other_list) ⇒ Object
Return a new list that is the intersection of the current list and one that’s passed in. The equivalent of calling (list1 ^ list2) in ink.
269 270 271 272 273 274 275 276 277 278 |
# File 'lib/fable/ink_list.rb', line 269 def &(other_list) intersection_list = self.class.new self.list.each do |item, int_value| if other_list.list.any?{|other_item, other_value| other_item.equal?(item)} intersection_list.list[item] = int_value end end return intersection_list end |
#+(other_list) ⇒ Object
Return a new list that is a combination of the current list and one that’s passed in. The equivalent of calling (list1 + list2) in ink.
258 259 260 261 262 263 264 265 |
# File 'lib/fable/ink_list.rb', line 258 def +(other_list) union_list = self.class.copy_list(self) other_list.list.each do |item, int_value| union_list.list[item] = int_value end return union_list end |
#-(other_list) ⇒ Object
Returns a new list that’s the same as the current one, except with the given items removed that are in the passed-in list. Equivalent to calling (list1 - list2) in ink.
283 284 285 286 287 288 289 290 |
# File 'lib/fable/ink_list.rb', line 283 def -(other_list) without_list = self.class.copy_list(self) other_list.list.each do |item, int_value| without_list.list.delete_if{ |without_list_item, other_value| without_list_item.equal?(item)} end return without_list end |
#<(other_list) ⇒ Object
Returns true if all the item values in the current list are less than all the item values in the passed-in list. Equivalent to calling (list1 < list2 in ink)
325 326 327 328 329 330 |
# File 'lib/fable/ink_list.rb', line 325 def <(other_list) return false if other_list.list.empty? return true if self.list.empty? return self.max_item[1] < other_list.min_item[1] end |
#<=(other_list) ⇒ Object
Returns true if the item values in the current list overlap, or are all less than the item values in the passed in list. None of the item values in the current list must go above the item values in the passed in list. Equivalent to (list1 <= list2) in ink, or LIST_MAX(list1) <= LIST_MAX(list2) && LIST_MIN(list1) <= LIST_MIN(list2)
336 337 338 339 340 341 342 343 344 |
# File 'lib/fable/ink_list.rb', line 336 def <=(other_list) return false if other_list.list.empty? return true if self.list.empty? return ( self.max_item[1] <= other_list.max_item[1] && self.min_item[1] <= other_list.min_item[1] ) end |
#==(other_list) ⇒ Object
Returns true if the passed object is also an ink list that contains the same items as the current list, false otherwise.
400 401 402 403 404 405 |
# File 'lib/fable/ink_list.rb', line 400 def ==(other_list) return false if !other_list.is_a?(InkList) return false if other_list.list.size != self.list.size return self.list.all?{|item, int_value| other_list.list.has_key?(item) } end |
#>(other_list) ⇒ Object
Returns true if all the item values in the current list are greater than all the item values in the passed-in list. Equivalent to calling (list1 > list2) in ink.
301 302 303 304 305 306 |
# File 'lib/fable/ink_list.rb', line 301 def >(other_list) return false if self.list.empty? return true if other_list.list.empty? return self.min_item[1] > other_list.max_item[1] end |
#>=(other_list) ⇒ Object
Returns true if the item values in the current list overlap, or are all greater than the item values in the passed-in list. None of the item values in the current list must fall below the item values in the passed-in list Equivalent to (list1 >= list2) in ink, or LIST_MIN(list1) >= LIST_MIN(list2) && LIST_MAX(list1) >= LIST_MAX(list2)
313 314 315 316 317 318 319 320 321 |
# File 'lib/fable/ink_list.rb', line 313 def >=(other_list) return false if self.list.empty? return true if other_list.list.empty? return ( self.min_item[1] >= other_list.min_item[1] && self.max_item[1] >= other_list.max_item[1] ) end |
#add_ink_list_item(item) ⇒ Object
Adds the given item to the ink list. Note that the item must come from a list definition that is already “known” to this list, so that teh item’s value can be looked up. By “known”, we mean that it alreadyu has items in it from that source, or did at one point. It can’t be a completely fresh empty list, or a list that only contains items from a different list definition
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/fable/ink_list.rb', line 128 def add_ink_list_item(item) if item.origin_name.nil? return add_item_from_string(item.item_name) end origins.each do |origin| if origin.name == item.origin_name integer_value = origin.items[item] if integer_value.nil? raise Error("Could not add the item '#{item.item_name}' to this list because it doesn't exist in the original list definition in ink.") else self.list[item] = integer_value end end end raise Error("Failed to add item to list because the item was from a new list definition that wasn't previously known to this list. Only items from previously known lists can be used, so that the int value can be found.") end |
#add_item(item_or_item_name) ⇒ Object
115 116 117 118 119 120 121 |
# File 'lib/fable/ink_list.rb', line 115 def add_item(item_or_item_name) if item_or_item_name.is_a?(InkListItem) add_ink_list_item(item_or_item_name) else add_item_from_string(item_or_item_name) end end |
#add_item_from_string(item_name) ⇒ Object
Adds the given item to the ink list, attempting to find the origin list definition that it belongs to. The item must therefore come from a list definition that is already “known” to this list, so that the item’s value can be looked up. By “known”, we mean that it already has items in it from that source, or it did at one point. It can’t be a completely fresh empty list, or a list that only contains items from a different list definition
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/fable/ink_list.rb', line 153 def add_item_from_string(item_name) found_list_definition = nil origins.each do |origin| if origin.items.any?{|item, int_value| item.name == item_name } if found_list_definition.nil? found_list_definition = origin else raise Error("Could not add the item '#{item_name}' to this list because it could come from either '#{origin.name}' or '#{found_list_definition.name}'") end end end if found_list_definition.nil? raise Error("Could not add the item '#{item_name}' to this list because it isn't known to any list definitions previously associated with this list.") end item = InkListItem.new(origin_name: found_list_definition.name, item_name: item_name) item_value = found_list_definition.value_for_item(item) self.items[item] = item_value end |
#all ⇒ Object
The list of all items from the original list definition, equivalent to calling LIST_ALL(list) in ink.
245 246 247 248 249 250 251 252 253 254 |
# File 'lib/fable/ink_list.rb', line 245 def all new_list = self.class.new origins.each do |origin| origin.items.each do |item, int_value| new_list.list[item] = int_value end end new_list end |
#contains?(other_list) ⇒ Boolean
Returns true if the current list contains all the items that are in the list that is passed in. Equivalent to calling (list1 ? list2) in ink.
294 295 296 |
# File 'lib/fable/ink_list.rb', line 294 def contains?(other_list) other_list.list.all?{|other_item, other_value| self.list.any?{|item, value| other_item.equal?(item) }} end |
#count ⇒ Object
207 208 209 |
# File 'lib/fable/ink_list.rb', line 207 def count list.size end |
#include_item_named?(item_name) ⇒ Boolean
174 175 176 |
# File 'lib/fable/ink_list.rb', line 174 def include_item_named?(item_name) list.any?{|item, int_value| item.name == item_name} end |
#inverse ⇒ Object
The inverse of the list, equivalent to colling LIST_INVERSE(list) in ink.
230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/fable/ink_list.rb', line 230 def inverse new_list = self.class.new origins.each do |origin| origin.items.each do |item, int_value| if self.list.none?{|item_to_search, other_value| item_to_search.equal?(item)} new_list.list[item] = int_value end end end new_list end |
#item_with_value(value) ⇒ Object
111 112 113 |
# File 'lib/fable/ink_list.rb', line 111 def item_with_value(value) list.key(value) end |
#list_with_subrange(min_bound, max_bound) ⇒ Object
Returns a sublist with the elements given in the minimum & maximum bounds. The bounds can either be ints, which are indicies into the entire (sorted) list, or they can be InkLists themsevles. These are intended to be single-item lists, so you can specify the upper & lower bounds. If you pass in multi-item lists, it’ll use the minimum and maximum items in those lists, respectively.
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
# File 'lib/fable/ink_list.rb', line 367 def list_with_subrange(min_bound, max_bound) return self.class.new if self.list.empty? ordered = self.ordered_items min_value = 0 max_value = Float::INFINITY if min_bound.is_a?(Numeric) min_value = min_bound elsif min_bound.is_a?(InkList) && !min_bound.list.empty? min_value = min_bound.min_item[1] end if max_bound.is_a?(Numeric) max_value = max_bound elsif max_bound.is_a?(InkList) && !max_bound.list.empty? max_value = max_bound.max_item[1] end sublist = self.class.new sublist.set_initial_origin_names(origin_names) ordered.each do |item, int_value| if int_value >= min_value && int_value <= max_value sublist.list[item] = int_value end end sublist end |
#max_as_list ⇒ Object
346 347 348 349 350 351 352 |
# File 'lib/fable/ink_list.rb', line 346 def max_as_list if self.list.empty? return self.class.new else return self.class.new_with_single_item(max_item) end end |
#max_item ⇒ Object
Get the maximum item in the list, equivalent to calling LIST_MAX(list) in ink.
212 213 214 215 216 217 218 |
# File 'lib/fable/ink_list.rb', line 212 def max_item list.max do |a, b| return -1 if a[0].null_item? return 1 if b[0].null_item? a[1] <=> b[1] end end |
#min_as_list ⇒ Object
354 355 356 357 358 359 360 |
# File 'lib/fable/ink_list.rb', line 354 def min_as_list if self.list.empty? return self.class.new else return self.class.new_with_single_item(min_item) end end |
#min_item ⇒ Object
Get the minimum item in the list, equivalent to calling LIST_MIN(list) in ink.
221 222 223 224 225 226 227 |
# File 'lib/fable/ink_list.rb', line 221 def min_item list.min do |a, b| return -1 if a[0].null_item? return 1 if b[0].null_item? a[1] <=> b[1] end end |
#ordered_items ⇒ Object
407 408 409 410 411 412 413 414 415 416 |
# File 'lib/fable/ink_list.rb', line 407 def ordered_items self.list.sort do |a, b| # ensure consistent ordering of mixed lists if(a[1] == b[1]) a[0].origin_name <=> b[0].origin_name else a[1] <=> b[1] end end end |
#origin_names ⇒ Object
Origin name needs to be serialized when content is empty, assuming a name is available, for list definitions with variable that is currently empty
191 192 193 194 195 196 197 |
# File 'lib/fable/ink_list.rb', line 191 def origin_names if self.list.any? @origin_names = self.list.map{|item, int_value| item.origin_name }.compact.uniq end return @origin_names end |
#origin_of_max_item ⇒ Object
Story has to set this so that the value knows its origin, necessary for certain operations (eg: iteracting with ints). Only the story has access to the full set of lists, so that the origin can be resolved from the origin_list_name
182 183 184 185 186 |
# File 'lib/fable/ink_list.rb', line 182 def origin_of_max_item return nil if origins.nil? max_origin_name = max_item.origin_name origins.find{|origin| origin.name == max_origin_name } end |
#set_initial_origin_name(initial_origin_name) ⇒ Object
199 200 201 |
# File 'lib/fable/ink_list.rb', line 199 def set_initial_origin_name(initial_origin_name) @origin_names = [initial_origin_name] end |
#set_initial_origin_names(initial_origin_names) ⇒ Object
203 204 205 |
# File 'lib/fable/ink_list.rb', line 203 def set_initial_origin_names(initial_origin_names) @origin_names = initial_origin_names end |
#to_s ⇒ Object
Returns a string in the form “a, b, c” with the names of the items in the list, without the origin list definition names. Equivalent to writing #list in ink
421 422 423 |
# File 'lib/fable/ink_list.rb', line 421 def to_s ordered_items.map{|item, int_value| item.item_name }.join(", ") end |