require 'sprite_factory'
require 'xiv_data'
namespace :data do
desc 'Initialize all data'
task initialize: :environment do
Rake::Task['sources:create_types'].invoke
Rake::Task['data:update'].invoke
Rake::Task['sources:initialize'].invoke
Rake::Task['relics:create'].invoke
Rake::Task['records:create'].invoke
Rake::Task['records:sources:create'].invoke
Rake::Task['hairstyles:vierify'].invoke
end
desc 'Updates all data'
task update: :environment do
unless Dir.exist?(XIVData::IMAGE_PATH)
puts "ERROR: Could not find image source directory: #{XIVData::IMAGE_PATH}"
puts 'Images will not be generated.'
end
unless Dir.exist?(XIVData::MUSIC_PATH)
puts "ERROR: Could not find music source directory: #{XIVData::MUSIC_PATH}"
puts 'Music samples will not be generated.'
end
Rake::Task['items:create'].invoke
Rake::Task['instances:create'].invoke
Rake::Task['quests:create'].invoke
Rake::Task['achievements:create'].invoke
Rake::Task['titles:create'].invoke
Rake::Task['mounts:create'].invoke
Rake::Task['minions:create'].invoke
Rake::Task['orchestrions:create'].invoke
Rake::Task['emotes:create'].invoke
Rake::Task['bardings:create'].invoke
Rake::Task['hairstyles:create'].invoke
Rake::Task['armoires:create'].invoke
Rake::Task['spells:create'].invoke
Rake::Task['fashions:create'].invoke
Rake::Task['records:create'].invoke
Rake::Task['items:set_unlocks'].invoke
Rake::Task['items:set_extras'].invoke
Rake::Task['sources:update'].invoke
Rake::Task['shops:sources:update'].invoke
Rake::Task['tomestones:images:create'].invoke
end
end
# Replace various tags with the appropriate text
def sanitize_text(text, preserve_space: false)
text = text.gsub('', "\u00AD")
.gsub(/(.*?)<\/Case>.*?<\/Switch>/m, '\1')
.gsub(/(.*?).*?<\/If>/m, '\1')
.gsub(/<\/?Emphasis>/, '*')
.gsub(/.*?<\/UIGlow>(.*?).*?<\/UIForeground>/, '**\1**')
.gsub('', ' ')
.gsub(/<.*?>(.*?)<\/.*?>/, '')
unless preserve_space
text = text.gsub("\r", "\n").gsub("\n", ' ')
end
text.strip
end
def sanitize_skill_description(text)
text.gsub('', "\u00AD")
.gsub(/.*?<\/UIGlow>(.*?).*?<\/UIForeground>/, '**\1**')
.gsub('', ' ')
.gsub(/<.*?>(.*?)<\/.*?>/, '')
.strip
end
# Titleize names and translate various tags
def sanitize_name(name)
name = name.split(' ').each { |s| s[0] = s[0].upcase }.join(' ')
name.gsub('[t]', 'der')
.gsub('[a]', 'e')
.gsub('[A]', 'er')
.gsub('[p]', '')
.gsub(/\uE0BE ?/, '')
.gsub('', "\u00AD")
.gsub('', ' ')
.gsub(/\<.*?\>/, '')
.gsub(/\((.)/) { |match| match.upcase } # (extreme) → (Extreme)
end
def without_custom(data)
data.symbolize_keys.except(:name_en, :name_fr, :name_de, :name_ja, :patch)
end
def updated?(model, data)
data.symbolize_keys!
current = model.attributes.symbolize_keys.select { |k, _| data.keys.include?(k) }
# The XIVData values are all strings, so convert integers to strings for comparison
current.each do |k, v|
current[k] = v.to_s if v.is_a?(Integer)
end
if updated = data != current
puts " Found new data for #{model.name_en} (#{model.id}):"
diff = data.map do |k, v|
"#{k}: #{current[k]} → #{v}" if current[k] != v
end
puts " #{diff.compact.join(', ')}"
end
updated
end
def link_music(path)
return unless Dir.exist?(XIVData::MUSIC_PATH)
FileUtils.ln_s(path, Rails.root.join('public/music', path.sub(/.*\//, '')), force: true)
end
def create_image(id, icon_path, path, mask_from = nil, mask_to = nil, width = nil, height = nil)
return unless Dir.exist?(XIVData::IMAGE_PATH)
# Use the custom output pathname if provided, otherwise generate it
if path.class == Pathname
output_path = path
else
output_path = Rails.root.join('public/images', path, "#{id}.png")
end
unless output_path.exist?
image_path = XIVData.image_path(icon_path)
begin
if mask_from.present?
mask_to ||= mask_from
image = ChunkyPNG::Image.from_file(image_path)
image.change_theme_color!(ChunkyPNG::Color.from_hex(mask_from), ChunkyPNG::Color.from_hex(mask_to),
ChunkyPNG::Color::TRANSPARENT)
elsif width.present?
image = ChunkyPNG::Image.from_file(image_path)
image.resample_bilinear!(width, height)
else
image = open(image_path).read
end
open(output_path.to_s, 'wb') { |file| file << image }
rescue Exception
puts "Could not create image: #{output_path}"
end
end
end
def create_spritesheet(path)
output_image = path.sub('/', '-')
class_name = output_image.singularize
options = { style: :scss, layout: :packed, library: :chunkypng,
nocomments: true, output_image: Rails.root.join('app/assets/images', "#{output_image}.png"),
output_style: Rails.root.join('app/assets/stylesheets/images', "#{output_image}.scss") }
SpriteFactory.run!(Rails.root.join('public/images', path), options) do |images|
rules = []
image = images.values.first
rules << "img.#{class_name} { width: #{image[:width]}px; height: #{image[:height]}px; " \
"background: url(image_path('#{output_image}.png')) no-repeat }"
images.each do |_, img|
rules << "img.#{class_name}-#{img[:name]} { background-position: #{-img[:cssx]}px #{-img[:cssy]}px }"
end
rules.join("\n")
end
end
def create_hair_spritesheets
Hairstyle.all.each do |hairstyle|
sheet = ChunkyPNG::Image.new(192 * 16, 192)
Dir.glob(Rails.root.join('public/images/hairstyles', hairstyle.id.to_s, '*.png')).sort.each_with_index do |image, i|
sheet.compose!(ChunkyPNG::Image.from_file(image), 192 * i, 0)
end
sheet.save(Rails.root.join('app/assets/images/hairstyles', "#{hairstyle.id}.png").to_s)
end
end