259 lines
5.7 KiB
Ruby
259 lines
5.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rubygems'
|
|
require 'httparty'
|
|
require 'strscan'
|
|
require 'pry'
|
|
|
|
# GranblueWiki fetches and parses data from gbf.wiki
|
|
class GranblueWiki
|
|
URL = 'https://gbf.wiki/api.php'
|
|
|
|
PROFICIENCY_MAP = {
|
|
'Sabre' => 1,
|
|
'Dagger' => 2,
|
|
'Axe' => 3,
|
|
'Spear' => 4,
|
|
'Bow' => 5,
|
|
'Staff' => 6,
|
|
'Melee' => 7,
|
|
'Harp' => 8,
|
|
'Gun' => 9,
|
|
'Katana' => 10
|
|
}
|
|
|
|
ELEMENT_MAP = {
|
|
'Wind' => 1,
|
|
'Fire' => 2,
|
|
'Water' => 3,
|
|
'Earth' => 4,
|
|
'Dark' => 5,
|
|
'Light' => 6
|
|
}
|
|
|
|
RARITY_MAP = {
|
|
'R' => 1,
|
|
'SR' => 2,
|
|
'SSR' => 3
|
|
}
|
|
|
|
RACE_MAP = {
|
|
'Other' => 0,
|
|
'Human' => 1,
|
|
'Erune' => 2,
|
|
'Draph' => 3,
|
|
'Harvin' => 4,
|
|
'Primal' => 5
|
|
}
|
|
|
|
GENDER_MAP = {
|
|
'o' => 0,
|
|
'm' => 1,
|
|
'f' => 2,
|
|
'mf' => 3
|
|
}
|
|
|
|
BOOLEAN_MAP = {
|
|
'yes' => true,
|
|
'no' => false
|
|
}
|
|
|
|
def fetch(page)
|
|
query_params = params(page).map do |key, value|
|
|
"#{key}=#{value}"
|
|
end.join('&')
|
|
|
|
destination = "#{URL}?#{query_params}"
|
|
response = HTTParty.get(destination)
|
|
|
|
response['parse']['wikitext']['*']
|
|
end
|
|
|
|
def save_characters(characters)
|
|
success = 0
|
|
characters.each do |chara|
|
|
success += 1 if parse(chara)
|
|
end
|
|
puts "Saved #{success} characters to the database"
|
|
end
|
|
def parse(page)
|
|
parsed = parse_string(fetch(page))
|
|
info = extract_chara_info(parsed)
|
|
create_character(info)
|
|
|
|
# abilities = extract_abilities(parsed)
|
|
# ougis = extract_ougis(parsed)
|
|
|
|
# ap abilities.merge(ougis)
|
|
end
|
|
|
|
def extract_chara_info(hash)
|
|
info = Hash.new
|
|
|
|
info[:name] = {
|
|
en: hash['name'],
|
|
ja: hash['jpname']
|
|
}
|
|
info[:id] = hash['id']
|
|
info[:charid] = hash['charid'].scan(/\b\d{4}\b/)
|
|
|
|
info[:flb] = BOOLEAN_MAP.fetch(hash['5star'], false)
|
|
info[:ulb] = true if hash['max_evo'].to_i == 6
|
|
|
|
info[:rarity] = RARITY_MAP.fetch(hash['rarity'], 0)
|
|
info[:element] = ELEMENT_MAP.fetch(hash['element'], 0)
|
|
info[:gender] = GENDER_MAP.fetch(hash['gender'], 0)
|
|
|
|
profs = hash['weapon'].to_s.split(',')
|
|
proficiencies = profs.map.with_index do |prof, i|
|
|
{ "proficiency#{i + 1}" => PROFICIENCY_MAP[prof] }
|
|
end
|
|
info[:proficiencies] = proficiencies.reduce({}, :merge)
|
|
|
|
races = hash['race'].to_s.split(',')
|
|
mapped_races = races.map.with_index do |race, i|
|
|
{ "race#{i + 1}" => RACE_MAP[race] }
|
|
end
|
|
info[:races] = mapped_races.reduce({}, :merge)
|
|
|
|
info[:hp] = {
|
|
min_hp: hash['min_hp'].to_i,
|
|
max_hp: hash['max_hp'].to_i,
|
|
max_hp_flb: hash['flb_hp'].to_i
|
|
}
|
|
|
|
info[:atk] = {
|
|
min_atk: hash['min_atk'].to_i,
|
|
max_atk: hash['max_atk'].to_i,
|
|
max_atk_flb: hash['flb_atk'].to_i
|
|
}
|
|
|
|
{ 'info' => info.compact }
|
|
end
|
|
|
|
def create_character(hash)
|
|
info = hash['info']
|
|
|
|
c = Character.new
|
|
c.granblue_id = info[:id]
|
|
c.character_id = info[:charid]
|
|
c.name_en = info[:name][:en]
|
|
c.name_jp = info[:name][:ja]
|
|
c.flb = info[:flb]
|
|
c.ulb = info[:ulb] if info.key?(:ulb)
|
|
c.rarity = info[:rarity]
|
|
c.element = info[:element]
|
|
c.gender = info[:gender]
|
|
c.race1 = info[:races]['race1']
|
|
c.race2 = info[:races]['race2'] if info[:races].key?('race2')
|
|
c.proficiency1 = info[:proficiencies]['proficiency1']
|
|
c.proficiency2 = info[:proficiencies]['proficiency2'] if info[:proficiencies].key?('proficiency2')
|
|
c.min_hp = info[:hp][:min_hp]
|
|
c.max_hp = info[:hp][:max_hp]
|
|
c.max_hp_flb = info[:hp][:max_hp_flb]
|
|
c.min_atk = info[:atk][:min_atk]
|
|
c.max_atk = info[:atk][:max_atk]
|
|
c.max_atk_flb = info[:atk][:max_atk_flb]
|
|
|
|
if c.save
|
|
puts "Saved #{c.name_en} (#{c.granblue_id}) to the database"
|
|
true
|
|
end
|
|
|
|
false
|
|
end
|
|
|
|
def extract_abilities(hash)
|
|
abilities = []
|
|
hash.each do |key, value|
|
|
next unless key =~ /^a(\d+)_/
|
|
|
|
ability_number = Regexp.last_match(1).to_i
|
|
abilities[ability_number] ||= {}
|
|
|
|
case key.gsub(/^a\d+_/, '')
|
|
when 'cd'
|
|
cooldown = parse_substring(value)
|
|
abilities[ability_number]['cooldown'] = cooldown
|
|
when 'dur'
|
|
duration = parse_substring(value)
|
|
abilities[ability_number]['duration'] = duration
|
|
when 'oblevel'
|
|
obtained = parse_substring(value)
|
|
abilities[ability_number]['obtained'] = obtained
|
|
else
|
|
abilities[ability_number][key.gsub(/^a\d+_/, '')] = value
|
|
end
|
|
end
|
|
|
|
{ 'abilities' => abilities.compact }
|
|
end
|
|
|
|
def parse_substring(string)
|
|
hash = {}
|
|
|
|
string.scan(/\|([^|=]+?)=([^|]+)/) do |key, value|
|
|
value.gsub!(/\}\}$/, '') if value.include?('}}')
|
|
hash[key] = value
|
|
end
|
|
|
|
hash
|
|
end
|
|
|
|
def extract_ougis(hash)
|
|
ougi = []
|
|
hash.each do |key, value|
|
|
next unless key =~ /^ougi(\d*)_(.*)/
|
|
|
|
ougi_number = Regexp.last_match(1)
|
|
ougi_key = Regexp.last_match(2)
|
|
ougi[ougi_number.to_i] ||= {}
|
|
ougi[ougi_number.to_i][ougi_key] = value
|
|
end
|
|
|
|
{ 'ougis' => ougi.compact }
|
|
end
|
|
|
|
def parse_string(string)
|
|
# Split the string into lines
|
|
lines = string.split("\n")
|
|
|
|
# Initialize an empty hash to store the key/value pairs
|
|
data = {}
|
|
|
|
# Iterate over the lines
|
|
good_lines = lines.map do |line|
|
|
line if line[0] == '|' && line.size > 2
|
|
end
|
|
|
|
good_lines.compact.each do |line|
|
|
trimmed_line = line[1..]
|
|
|
|
# Split the line into key and value by the '=' character
|
|
key, value = trimmed_line.split('=', 2)
|
|
|
|
next unless value
|
|
|
|
# Strip leading and trailing whitespace from the key and value
|
|
key = key.strip
|
|
value = value.strip
|
|
|
|
# Store the key/value pair in the data hash
|
|
data[key] = value
|
|
end
|
|
|
|
# Return the data hash
|
|
data
|
|
end
|
|
|
|
private
|
|
|
|
def params(page)
|
|
{
|
|
action: 'parse',
|
|
format: 'json',
|
|
page: page,
|
|
prop: 'wikitext'
|
|
}
|
|
end
|
|
end
|