-
Notifications
You must be signed in to change notification settings - Fork 0
/
dandd.rb
executable file
·145 lines (119 loc) · 4.01 KB
/
dandd.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/ruby
require_relative 'internal_ids'
require 'nokogiri'
require 'optparse'
def get_file_xml(filename)
xml = File.open(filename, 'rb') { |f| Nokogiri::XML(f) }
xml
end
def generate_new_partfile()
new_partfile = Nokogiri::XML::Document.new('1.0')
new_partfile.encoding = 'utf-8'
d20_node = Nokogiri::XML::Node.new('D20Rules', new_partfile)
d20_node.set_attribute('game-system', "D&D4E")
new_partfile.add_child(d20_node)
new_partfile
end
# Gets all RulesElements of the specified type. For example, Fighter, Cleric, Rogue.
def get_elements_of_type(xml, type)
types = []
xml.xpath('//RulesElement').each do |ruleselement|
if ruleselement.attr('type') == type
types << ruleselement.attr('name')
end
end
types
end
# Gets all types of RulesElement in the XML. For example, Class, Race, Power.
def get_all_types(xml)
types = []
xml.xpath('//RulesElement').each do |ruleselement|
if !types.include? ruleselement.attr('type')
types << ruleselement.attr('type')
end
end
types
end
# Copy an element to another.
def copy_element(xml, element_type, source, target)
# First, does this class even exist in this file?
elements = get_elements_of_type(xml, element_type)
unless elements.include?(source)
puts "I can't find #{element_type} #{source} in this file."
return nil
end
puts "DEBUG: Found #{element_type} #{source}."
target_xml = generate_new_partfile()
xml.xpath('//RulesElement').each do |ruleselement|
if ruleselement.attr('type') == element_type
if ruleselement.attr('name') == source
# We just duplicate the first one we find.
new_element = ruleselement.dup
new_element.set_attribute('name', target)
# Example internal ID for Fighter Class is ID_FMP_CLASS_793. These must be unique.
old_internal_id = ruleselement.attr('internal-id').rpartition('_')
internal_id_base = old_internal_id.first
internal_id_number = old_internal_id.last
puts "Please provide a unique internal ID number."
puts "(The internal ID number for #{source} is #{internal_id_number})"
internal_id_number = gets.chomp
new_element.set_attribute('internal-id', internal_id_base + "_" + internal_id_number)
target_xml.root.add_child(new_element)
end
end
end
target_xml
end
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
opts.on("-i", "--input-file FILENAME", "File to read data from.") do |i|
options[:input_file] = i
end
opts.on("-t", "--types", "List all types available in the input file.") do |t|
options[:types] = t
end
opts.on("-l", "--list TYPE", "List all elements of TYPE in the input file.") do |l|
options[:list] = l
end
opts.on("-c", "--copy-class CLASS", "Copy CLASS to a new class.") do |c|
options[:copyclass] = c
end
opts.on("-r", "--copy-race RACE", "Copy RACE to a new race.") do |r|
options[:copyrace] = r
end
opts.on("-d", "--destination NAME", "Destination to copy to.") do |d|
options[:destination] = d
end
opts.on('-h', '--help', 'Display this screen.') do
puts opts
exit
end
end.parse!
if options[:input_file]
xml = get_file_xml(options[:input_file])
# I decided not to make these mutually exclusive.
# If you want to list all types and then all objects of a particular one, go for it.
if options[:types]
types = get_all_types(xml)
puts "This file contains the following types of object:"
puts types.join(', ')
end
if options[:list]
desired_type = options[:list]
types = get_elements_of_type(xml, desired_type)
puts "All #{desired_type} objects found:"
puts types.join(', ')
end
if options[:copyclass]
source = options[:copyclass]
if options[:destination]
destination = options[:destination]
else
puts "What shall I copy #{source} to?"
destination = gets.chomp.capitalize
end
puts "DEBUG: Copying #{source} to #{destination}"
puts copy_element(xml, 'Class', source, destination)
end
end