Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 88 additions & 1 deletion spec/workorders_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,26 @@ def before_dying(&block)
expect(match[:remaining]).to eq('3')
end

it 'defines LOGBOOK_ITEM_PATTERN with named capture' do
pattern = described_class::LOGBOOK_ITEM_PATTERN
match = 'This logbook is tracking a work order requiring you to craft a curved metal shovel from any material.'.match(pattern)
expect(match).not_to be_nil
expect(match[:item]).to eq('a curved metal shovel')
end

it 'captures fabric items when remaining count is on the same line' do
line = 'This logbook is tracking a work order requiring you to craft a knitted napkin from any fabric. You must bundle and deliver 1 more within the next 2 roisaen.'
match = line.match(described_class::LOGBOOK_ITEM_PATTERN)
expect(match).not_to be_nil
expect(match[:item]).to eq('a knitted napkin')
expect(line.match(described_class::LOGBOOK_REMAINING_PATTERN)[:remaining]).to eq('1')
end

it 'defines RESUME_LOGBOOK_PATTERNS as frozen array including LOGBOOK_ITEM_PATTERN' do
expect(described_class::RESUME_LOGBOOK_PATTERNS).to be_frozen
expect(described_class::RESUME_LOGBOOK_PATTERNS).to include(described_class::LOGBOOK_ITEM_PATTERN)
end

it 'defines COUNT_PATTERN with named capture' do
pattern = described_class::COUNT_PATTERN
match = '42'.match(pattern)
Expand Down Expand Up @@ -169,7 +189,7 @@ def before_dying(&block)

it 'defines VERSION as frozen string' do
expect(described_class::VERSION).to be_frozen
expect(described_class::VERSION).to eq('1.0.0')
expect(described_class::VERSION).to eq('1.0.2')
end
end

Expand Down Expand Up @@ -349,6 +369,73 @@ def before_dying(&block)
end
end

# ===========================================================================
# #resume_work_order - parse active order from logbook for continue
# ===========================================================================
describe '#resume_work_order' do
let(:recipes) do
[
{ 'name' => 'a curved metal shovel', 'noun' => 'shovel', 'type' => 'blacksmithing' },
{ 'name' => 'a metal razor', 'noun' => 'razor', 'type' => 'blacksmithing' }
]
end

before do
allow(workorders).to receive(:stow_tool)
end

it 'returns recipe name and remaining count for an in-progress order' do
expect(DRCI).to receive(:get_item?).with('forging logbook').and_return(true)
# bput returns only the matched substring for the first matching pattern
expect(DRC).to receive(:bput).with('read my forging logbook', *described_class::RESUME_LOGBOOK_PATTERNS)
.and_return('This logbook is tracking a work order requiring you to craft a curved metal shovel from any')
expect(workorders).to receive(:logbook_remaining).with('forging').and_return(2)
expect(Lich::Messaging).to receive(:msg).with('plain', 'WorkOrders: Continuing work order for 2 a curved metal shovel')

expect(workorders.send(:resume_work_order, 'forging', recipes)).to eq(['a curved metal shovel', 2])
end

it 'parses knitted fabric orders from the truncated bput match' do
recipes = [{ 'name' => 'a knitted napkin', 'noun' => 'napkin', 'type' => 'tailoring', 'chapter' => 5 }]
expect(DRCI).to receive(:get_item?).with('outfitting logbook').and_return(true)
expect(DRC).to receive(:bput).with('read my outfitting logbook', *described_class::RESUME_LOGBOOK_PATTERNS)
.and_return('This logbook is tracking a work order requiring you to craft a knitted napkin from any')
expect(workorders).to receive(:logbook_remaining).with('outfitting').and_return(1)
expect(Lich::Messaging).to receive(:msg).with('plain', 'WorkOrders: Continuing work order for 1 a knitted napkin')

expect(workorders.send(:resume_work_order, 'outfitting', recipes)).to eq(['a knitted napkin', 1])
end

it 'returns quantity 0 when logbook order appears complete' do
expect(DRCI).to receive(:get_item?).with('forging logbook').and_return(true)
expect(DRC).to receive(:bput).with('read my forging logbook', *described_class::RESUME_LOGBOOK_PATTERNS)
.and_return('This work order appears to be complete.')
expect(Lich::Messaging).to receive(:msg).with('plain', 'WorkOrders: Logbook order complete — turning in')

expect(workorders.send(:resume_work_order, 'forging', recipes)).to eq([nil, 0])
end

it 'exits when logbook has no in-progress work order' do
expect(DRCI).to receive(:get_item?).with('forging logbook').and_return(true)
expect(DRC).to receive(:bput).with('read my forging logbook', *described_class::RESUME_LOGBOOK_PATTERNS)
.and_return('This logbook is not currently tracking a work order.')
expect(Lich::Messaging).to receive(:msg).with('bold', 'WorkOrders: No in-progress work order in forging logbook')
expect(workorders).to receive(:exit).and_raise(SystemExit)

expect { workorders.send(:resume_work_order, 'forging', recipes) }.to raise_error(SystemExit)
end

it 'exits when logbook item does not match a recipe' do
expect(DRCI).to receive(:get_item?).with('forging logbook').and_return(true)
expect(DRC).to receive(:bput).with('read my forging logbook', *described_class::RESUME_LOGBOOK_PATTERNS)
.and_return('This logbook is tracking a work order requiring you to craft a metal unknown widget from any')
expect(Lich::Messaging).to receive(:msg).with('bold', "WorkOrders: Could not match logbook item 'a metal unknown widget' to a recipe")
expect(workorders).to receive(:exit).and_raise(SystemExit)

expect { workorders.send(:resume_work_order, 'forging', recipes) }.to raise_error(SystemExit)
end
end

# ===========================================================================
# #bundle_item - pattern matching for success/failure
# ===========================================================================
Expand Down
111 changes: 95 additions & 16 deletions workorders.lic
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
=end

class WorkOrders
VERSION = '1.0.0'.freeze
VERSION = '1.0.2'.freeze

# Pattern constants for game responses
GIVE_LOGBOOK_SUCCESS_PATTERNS = [
Expand Down Expand Up @@ -78,8 +78,19 @@ class WorkOrders
'You must bundle and deliver \d+ more'
].freeze

# Full item capture must be used in bput — a shorter prefix match returns only the
# matched substring and drops the item name (item + remaining are often one line).
LOGBOOK_ITEM_PATTERN = /This logbook is tracking a work order requiring you to craft (?<item>.+?) from any/i.freeze
LOGBOOK_REMAINING_PATTERN = /You must bundle and deliver (?<remaining>\d+) more/.freeze

RESUME_LOGBOOK_PATTERNS = [
LOGBOOK_ITEM_PATTERN,
'This work order appears to be complete.',
'is not currently tracking',
'has expired',
LOGBOOK_REMAINING_PATTERN
].freeze

COUNT_PATTERN = /(?<count>\d+)/.freeze
POLISH_COUNT_PATTERN = /The surface polish has (?<count>\d+) uses remaining/.freeze

Expand All @@ -95,15 +106,16 @@ class WorkOrders
[
{ name: 'discipline', options: %w[blacksmithing weaponsmithing tailoring shaping carving remedies artificing], description: 'What type of workorder to do?' },
{ name: 'repair', regex: /repair/i, optional: true, description: 'repair tools instead of crafting' },
{ name: 'turnin', regex: /turnin/i, optional: true, description: 'get work order and turn it in immediately with items already on hand' }
{ name: 'turnin', regex: /turnin/i, optional: true, description: 'get work order and turn it in immediately with items already on hand' },
{ name: 'continue', regex: /continue/i, optional: true, description: 'resume an in-progress workorder from the logbook' }
]
]

args = parse_args(arg_definitions)
work_order(args.discipline, args.repair, args.turnin)
work_order(args.discipline, args.repair, args.turnin, args.continue)
end

def work_order(discipline, repair, turnin)
def work_order(discipline, repair, turnin, continue_order = nil)
@settings = get_settings
@worn_trashcan = @settings.worn_trashcan
@worn_trashcan_verb = @settings.worn_trashcan_verb
Expand Down Expand Up @@ -148,7 +160,12 @@ class WorkOrders
exit
end

unless repair
item = nil
quantity = nil
if continue_order
item_name, quantity = resume_work_order(info['logbook'], recipes)
item = recipes.find { |r| r['name'] == item_name } if item_name
elsif !repair
if @settings.workorder_diff.is_a?(Hash)
item_name, quantity = request_work_order(recipes, info['npc-rooms'], info['npc'], info['npc_last_name'], discipline, info['logbook'], @settings.workorder_diff[discipline])
else
Expand Down Expand Up @@ -176,16 +193,18 @@ class WorkOrders
@outfitting_room = @settings.outfitting_room
tools = @settings.outfitting_tools
@belt = @settings.outfitting_belt
case item['chapter']
when 4, 2, 3
craft_method = :sew_items
when 5
materials_info = crafting_data['stock'][@workorders_materials['knit_type']]
craft_method = :knit_items
else
if item['chapter']
Lich::Messaging.msg('bold', "WorkOrders: Unknown chapter for tailoring item: #{item}")
exit
if item
case item['chapter']
when 4, 2, 3
craft_method = :sew_items
when 5
materials_info = crafting_data['stock'][@workorders_materials['knit_type']]
craft_method = :knit_items
else
if item['chapter']
Lich::Messaging.msg('bold', "WorkOrders: Unknown chapter for tailoring item: #{item}")
exit
end
end
end
when 'shaping'
Expand Down Expand Up @@ -225,12 +244,18 @@ class WorkOrders

return repair_items(info, tools) if repair

if continue_order && quantity.zero?
complete_work_order(info)
repair_items(info, tools) if @workorders_repair
return
end

if DRSkill.getxp(skill) > @craft_max_mindstate
Lich::Messaging.msg('bold', "WorkOrders: Exiting because your current mindstate for #{skill} (#{DRSkill.getxp(skill)}) is over the set maximum craft_max_mindstate: #{@craft_max_mindstate}")
exit
end

if turnin
if turnin && !continue_order
quantity.times do
DRCI.get_item(item['noun'], @settings.default_container)
bundle_item(item['noun'], info['logbook'])
Expand Down Expand Up @@ -282,6 +307,60 @@ class WorkOrders
nil
end

# Resume an in-progress work order from the discipline logbook.
# @return [Array(String, Integer)] recipe name and remaining quantity (0 if complete)
def resume_work_order(logbook, recipes)
unless DRCI.get_item?("#{logbook} logbook")
Lich::Messaging.msg('bold', "WorkOrders: Failed to get #{logbook} logbook")
exit
end

result = DRC.bput("read my #{logbook} logbook", *RESUME_LOGBOOK_PATTERNS)

if result.include?('appears to be complete')
stow_tool('logbook')
Lich::Messaging.msg('plain', 'WorkOrders: Logbook order complete — turning in')
return [nil, 0]
end

if result.include?('not currently tracking') || result.include?('has expired')
stow_tool('logbook')
Lich::Messaging.msg('bold', "WorkOrders: No in-progress work order in #{logbook} logbook")
exit
end

match = result.match(LOGBOOK_ITEM_PATTERN)
unless match
stow_tool('logbook')
Lich::Messaging.msg('bold', "WorkOrders: Could not parse item from #{logbook} logbook")
exit
end

item_desc = match[:item]
recipe = recipes.find { |r| r['name'] == item_desc }
unless recipe
stow_tool('logbook')
Lich::Messaging.msg('bold', "WorkOrders: Could not match logbook item '#{item_desc}' to a recipe")
exit
end

remaining = logbook_remaining(logbook)
stow_tool('logbook')

if remaining.nil?
Lich::Messaging.msg('bold', "WorkOrders: Could not read remaining count from #{logbook} logbook")
exit
end

if remaining.zero?
Lich::Messaging.msg('plain', 'WorkOrders: Logbook order complete — turning in')
return [recipe['name'], 0]
end

Lich::Messaging.msg('plain', "WorkOrders: Continuing work order for #{remaining} #{recipe['name']}")
[recipe['name'], remaining]
end

def get_tool(name)
DRCC.get_crafting_item(name, @bag, @bag_items, @belt, true)
end
Expand Down
Loading