Add bin and edit workflow
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 9s

This commit is contained in:
2026-09-16 13:11:16 -06:00
parent c8ac4fcae5
commit 4cee170d66
17576 changed files with 895740 additions and 2 deletions
@@ -0,0 +1,152 @@
unless defined?(MSlinnBinarySearchError)
class MSlinnBinarySearchError < StandardError
end
end
# Ruby's binary search is unsuitable because the value to be searched for changes the required ordering for String compares
class MSlinnBinarySearch
attr_reader :accessor_chain, :array # For testing only
def initialize(accessor_chain)
@array = SortedSet.new # [LruFile] Ordered highest to lowest
@accessor_chain = accessor_chain
end
# Convert the SortedSet to an Array
def enable_search
@array = @array.to_a
end
# A match is found when the Array[LruFile] has an href which starts with the given stem
# @param stem [String]
# @return first item from @array.url that matches, or nil if no match
def find(stem)
raise MSlinnBinarySearchError, 'Invalid find because stem to search for is nil.' if stem.nil?
index = find_index(stem)
return nil if index.nil?
@array[index]
end
# @param stem [String]
# @return index of first matching stem, or nil if @array is empty, or 0 if no stem specified
def find_index(stem)
return nil if @array.empty?
return 0 if stem.nil? || stem.empty?
mets = stem.reverse
return nil if @array[0].url[0...mets.size] > mets # TODO: use chain eval for item
return nil if @array[0].url[0] != mets[0]
_find_index(mets, 0, @array.length - 1)
end
# @param stem [String]
# @return [index] of matching values, or [] if @array is empty, or entire array if no stem specified
def find_indices(stem)
return [] if @array.empty?
return @array if stem.nil? || stem.empty?
first_index = _find_index(stem, 0, @array.length - 1)
last_index = first_index
last_index += 1 while @array[last_index].url.start_with? stem
[first_index..last_index]
end
# @param item [LruFile]
# @return [int] index of matching LruFile in @array, or nil if not found
def index_of(lru_file)
raise MSlinnBinarySearchError, 'Invalid index_of lru_file (nil).' if lru_file.nil?
find_index lru_file.url
end
# @return [LruFile] item at given index in @array
def item_at(index)
if index > @array.length - 1
raise MSlinnBinarySearchError,
"Invalid item_at index (#{index}) is greater than maximum stem (#{@array.length - 1})."
end
raise MSlinnBinarySearchError, "Invalid item_at index (#{index}) is less than zero." if index.negative?
@array[index]
end
# @param lru_file [LruFile]
def insert(lru_file)
raise MSlinnBinarySearchError, 'Invalid insert because new item is nil.' if lru_file.nil?
raise MSlinnBinarySearchError, "Invalid insert because new item has no chain (#{lru_file})" if lru_file.chain.nil?
@array.add lru_file
end
# TODO: Cache this method
# @param suffix [String] to use stem search on
# @return nil if @array is empty
# @return the first item in @array if suffix is nil or an empty string
def prefix_search(suffix)
return nil if @array.empty?
return @array[0] if suffix.empty? || suffix.nil?
low = search_index { |x| x.evaluate_with suffix }
return [] if low.nil?
high = low
high += 1 while high < @array.length &&
@array[high].evaluate_with(suffix)
@array[low..high]
end
# @param stem [String]
# @return [APage] matching APages, or [] if @array is empty, or entire array if no stem specified
def select_pages(stem)
first_index = find_index stem
return [] if first_index.nil?
last_index = first_index
while last_index < @array.length - 1
# LruFile.url is reversed, bug LruFile.page is not
break unless @array[last_index + 1].url.start_with?(stem.reverse)
last_index += 1
end
Range.new(first_index, last_index).map { |i| @array[i].page }
end
private
# A match is found when the Array[LruFile] has an href which starts with the given stem
# @param stem [String]
# @return [int] first index in @array that matches, or nil if no match
def _find_index(mets, min_index, max_index)
raise MSlinnBinarySearchError, "_find_index min_index(#{min_index})<0" if min_index.negative?
raise MSlinnBinarySearchError, "_find_index min_index(#{min_index})>max_index(#{max_index})" if min_index > max_index
raise MSlinnBinarySearchError, "_find_index max_index(#{max_index})>=@array.length(#{@array.length})" if max_index >= @array.length
return min_index if (min_index == max_index) && @array[min_index].url.start_with?(mets)
while min_index < max_index
mid_index = (min_index + max_index) / 2
mid_value = @array[mid_index].url[0...(mets.size)] # TODO: use chain eval for item
if mid_value == mets # back up until the first match is found
index = mid_index
loop do
return 0 if index.zero?
return index unless @array[index - 1].url.start_with?(mets)
index -= 1
end
elsif mid_value > mets
max_index = mid_index - 1
return _find_index(mets, min_index, max_index)
else
min_index = mid_index + 1
return _find_index(mets, min_index, max_index)
end
end
nil
end
end
@@ -0,0 +1,56 @@
# Supports one chain at a time
module SendChain
# See https://stackoverflow.com/a/79333706/553865
# This method can be called directly if no methods in the chain require arguments
# Does not use any external state
def send_chain(chain)
Array(chain).inject(self) { |o, a| o.send(*a) }
end
# Saves @chain structure containing :placeholders for arguments to be supplied later
# Call when a different chain with :placeholders is desired
def new_chain(chain)
abort "new_chain error: chain must be an array ('#{chain}' was an #{chain.class.name})" \
unless chain.instance_of?(Array)
@chain = chain
end
# Call after new_chain, to evaluate @chain with values
def substitute_and_send_chain_with(values)
send_chain substitute_chain_with values
end
alias evaluate_with substitute_and_send_chain_with
# Call this method after calling new_chain to perform error checking and replace :placeholders with values.
# @chain is not modified.
# @return [Array] Modified chain
def substitute_chain_with(values)
values = [values] unless values.instance_of?(Array)
placeholder_count = @chain.flatten.count { |x| x == :placeholder }
if values.length != placeholder_count
abort "with_values error: number of values (#{values.length}) does not match the number of placeholders (#{placeholder_count})"
end
eval_chain @chain, values
end
private
# Replaces :placeholders with values
# Does not use any external state
# @return modified chain
def eval_chain(chain, values)
chain.map do |c|
case c
when :placeholder
values.shift
when Array
eval_chain c, values
else
c
end
end
end
end