Class: Factorix::Dependency::List
- Inherits:
-
Object
- Object
- Factorix::Dependency::List
- Includes:
- Enumerable
- Defined in:
- lib/factorix/dependency/list.rb
Overview
Represents a collection of MOD dependencies
This class manages a collection of Dependency::Entry objects, providing filtering, validation, and circular dependency detection capabilities.
Class Method Summary collapse
-
.detect_circular(mod_dependencies_map) ⇒ Array<Array<String>>
Detect circular dependencies in a collection of MOD dependencies.
-
.from_strings(dependency_strings) ⇒ List
Create List from an array of dependency strings.
Instance Method Summary collapse
-
#conflicts_with?(available_mods) ⇒ Array<String>
Get list of incompatible MODs that are present.
-
#depends_on?(mod_name_or_mod) ⇒ Boolean
Check if this collection depends on a specific MOD.
-
#each {|dependency| ... } ⇒ Enumerator, List
Iterate through all dependencies.
-
#empty? ⇒ Boolean
Check if the collection is empty.
-
#incompatible ⇒ Array<Entry>
Get all incompatible dependencies.
-
#incompatible_with?(mod_name_or_mod) ⇒ Boolean
Check if this collection marks a MOD as incompatible.
-
#initialize(dependencies = []) ⇒ void
constructor
Initialize a List collection.
-
#load_neutral ⇒ Array<Entry>
Get all load-neutral dependencies.
-
#missing_required(available_mods) ⇒ Array<String>
Get list of missing required dependencies.
-
#optional ⇒ Array<Entry>
Get all optional dependencies (including hidden optional).
-
#required ⇒ Array<Entry>
Get all required dependencies.
-
#satisfied_by?(available_mods) ⇒ Boolean
Check if all required dependencies are satisfied.
-
#size ⇒ Integer
Get the total number of dependencies.
-
#to_a ⇒ Array<String>
Convert to array of dependency strings.
-
#to_h ⇒ Hash<String, Entry>
Convert to hash keyed by MOD name.
-
#unsatisfied_versions(available_mods) ⇒ Hash<String, Hash<Symbol, String>>
Get list of dependencies with unsatisfied version requirements.
Constructor Details
#initialize(dependencies = []) ⇒ void
Initialize a List collection
118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/factorix/dependency/list.rb', line 118 def initialize(dependencies=[]) unless dependencies.is_a?(Array) raise ArgumentError, "dependencies must be an Array, got #{dependencies.class}" end dependencies.each_with_index do |dep, index| unless dep.is_a?(Entry) raise ArgumentError, "dependencies[#{index}] must be a Dependency::Entry, got #{dep.class}" end end @dependencies = dependencies.freeze end |
Class Method Details
.detect_circular(mod_dependencies_map) ⇒ Array<Array<String>>
Detect circular dependencies in a collection of MOD dependencies
Uses TSort to detect cycles in the dependency graph. Only considers required dependencies (optional and load-neutral are ignored).
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/factorix/dependency/list.rb', line 90 def self.detect_circular(mod_dependencies_map) graph = DependencyGraph.new(mod_dependencies_map) cycles = [] # Detect self-dependencies (not detected by strongly_connected_components) mod_dependencies_map.each do |mod_name, deps| if deps.required.any? {|dep| dep.mod.name == mod_name } cycles << [mod_name, mod_name] end end # Get strongly connected components (cycles are components with size > 1) scc_cycles = graph.strongly_connected_components.filter_map {|component| next if component.size <= 1 # Add first element at the end to make cycle explicit component + [component.first] } cycles + scc_cycles end |
.from_strings(dependency_strings) ⇒ List
Create List from an array of dependency strings
69 70 71 72 73 |
# File 'lib/factorix/dependency/list.rb', line 69 def self.from_strings(dependency_strings) parser = Parser.new dependencies = dependency_strings.map {|str| parser.parse(str) } new(dependencies) end |
Instance Method Details
#conflicts_with?(available_mods) ⇒ Array<String>
Get list of incompatible MODs that are present
204 |
# File 'lib/factorix/dependency/list.rb', line 204 def conflicts_with?(available_mods) = incompatible.filter_map {|dep| dep.mod.name if available_mods.key?(dep.mod.name) } |
#depends_on?(mod_name_or_mod) ⇒ Boolean
Check if this collection depends on a specific MOD
168 169 170 171 172 |
# File 'lib/factorix/dependency/list.rb', line 168 def depends_on?(mod_name_or_mod) mod_name = mod_name_or_mod.is_a?(MOD) ? mod_name_or_mod.name : mod_name_or_mod.to_s @dependencies.any? {|dep| dep.mod.name == mod_name && !dep.incompatible? } end |
#each {|dependency| ... } ⇒ Enumerator, List
Iterate through all dependencies
137 138 139 140 141 142 |
# File 'lib/factorix/dependency/list.rb', line 137 def each(&block) return @dependencies.to_enum unless block @dependencies.each(&block) self end |
#empty? ⇒ Boolean
Check if the collection is empty
187 |
# File 'lib/factorix/dependency/list.rb', line 187 def empty? = @dependencies.empty? |
#incompatible ⇒ Array<Entry>
Get all incompatible dependencies
157 |
# File 'lib/factorix/dependency/list.rb', line 157 def incompatible = @dependencies.select(&:incompatible?) |
#incompatible_with?(mod_name_or_mod) ⇒ Boolean
Check if this collection marks a MOD as incompatible
178 179 180 181 182 |
# File 'lib/factorix/dependency/list.rb', line 178 def incompatible_with?(mod_name_or_mod) mod_name = mod_name_or_mod.is_a?(MOD) ? mod_name_or_mod.name : mod_name_or_mod.to_s @dependencies.any? {|dep| dep.mod.name == mod_name && dep.incompatible? } end |
#load_neutral ⇒ Array<Entry>
Get all load-neutral dependencies
162 |
# File 'lib/factorix/dependency/list.rb', line 162 def load_neutral = @dependencies.select(&:load_neutral?) |
#missing_required(available_mods) ⇒ Array<String>
Get list of missing required dependencies
210 |
# File 'lib/factorix/dependency/list.rb', line 210 def missing_required(available_mods) = required.filter_map {|dep| dep.mod.name unless available_mods.key?(dep.mod.name) } |
#optional ⇒ Array<Entry>
Get all optional dependencies (including hidden optional)
152 |
# File 'lib/factorix/dependency/list.rb', line 152 def optional = @dependencies.select(&:optional?) |
#required ⇒ Array<Entry>
Get all required dependencies
147 |
# File 'lib/factorix/dependency/list.rb', line 147 def required = @dependencies.select(&:required?) |
#satisfied_by?(available_mods) ⇒ Boolean
Check if all required dependencies are satisfied
198 |
# File 'lib/factorix/dependency/list.rb', line 198 def satisfied_by?(available_mods) = required.all? {|dep| (version = available_mods[dep.mod.name]) && dep.satisfied_by?(version) } |
#size ⇒ Integer
Get the total number of dependencies
192 |
# File 'lib/factorix/dependency/list.rb', line 192 def size = @dependencies.size |
#to_a ⇒ Array<String>
Convert to array of dependency strings
236 |
# File 'lib/factorix/dependency/list.rb', line 236 def to_a = @dependencies.map(&:to_s) |
#to_h ⇒ Hash<String, Entry>
Convert to hash keyed by MOD name
241 |
# File 'lib/factorix/dependency/list.rb', line 241 def to_h = @dependencies.to_h {|dep| [dep.mod.name, dep] } |
#unsatisfied_versions(available_mods) ⇒ Hash<String, Hash<Symbol, String>>
Get list of dependencies with unsatisfied version requirements
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/factorix/dependency/list.rb', line 216 def unsatisfied_versions(available_mods) result = {} required.each do |dep| next unless dep.version_requirement # Skip if no version requirement version = available_mods[dep.mod.name] next unless version # Skip if not available (covered by missing_required) next if dep.satisfied_by?(version) result[dep.mod.name] = {required: dep.version_requirement.to_s, actual: version.to_s} end result end |