Module: Adam::Killmail

Extended by:
Killmail
Included in:
Killmail
Defined in:
lib/adam/killmail.rb,
lib/adam/killmail/validation_error.rb

Defined Under Namespace

Classes: ValidationError

Instance Method Summary collapse

Instance Method Details

#parse(source) ⇒ Object

Parses killmails and populates corresponding Kill objects.

Parameters:

  • source - A string containing the killmail to parse.

Raises:



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
146
147
148
149
150
151
152
153
# File 'lib/adam/killmail.rb', line 19

def parse(source)
  raise ValidationError.new(source), "Killmail is empty" if source.empty?
  
  # Normalize line endings
  source.encode! :universal_newline => true

  Adam::Kill.new do |kill|
  
    time = source[/([0-9]{4}\.[0-9]{2}\.[0-9]{2} [0-9]{2}:[0-9]{2})/, 1] or raise ValidationError.new(source), "Time malformed"
    time = Time.parse(time + " UTC")
  
    kill.time = time
    
    kill.solar_system = Adam::Kill::SolarSystem.new do |ss|
      ss.name             = source[/System: (.+)/, 1] or raise ValidationError.new(source), "Solar system malformed"
      ss.security_status  = source[/Security: ([\.0-9]+)/, 1].to_f or raise ValidationError.new(source), "Solar system security malformed"
    end
    
    raise ValidationError.new(source), "No solar system called '#{kill.solar_system.name}' exists" unless SolarSystem.exists? :name => kill.solar_system.name
  
    kill.victim = Adam::Kill::Victim.new do |v|
      if source =~ /Victim:/
        v.pilot       = source[/Victim: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Victim pilot malformed"
      elsif source =~ /Moon:/
        v.moon        = source[/Moon: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Victim moon malformed"
      end
      v.corporation   = source[/Corp: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Victim corporation malformed"
      v.alliance      = source[/Alliance: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Victim alliance malformed"
      v.faction       = source[/Faction: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Victim faction malformed"
      v.ship          = source[/Destroyed: (.+)/, 1] or raise ValidationError.new(source), "Victim ship malformed"
      v.damage_taken  = source[/Damage Taken: ([0-9]+)/, 1].to_i or raise ValidationError.new(source), "Victim damage taken malformed"
  
      # Set pilot to nil if it's a moon
      v.pilot = nil if v.pilot =~ /[a-zA-Z0-9\- ]+ - Moon [0-9]+/
    
      # Convert alliance/faction from "unknown" or "none" to nil
      v.alliance = nil if v.alliance =~ /unknown|none/i
      v.faction = nil if v.faction =~ /unknown|none/i
    end
    
    raise ValidationError.new(source), "No faction called '#{kill.victim.faction}' exists" if kill.victim.faction and !Faction.exists? :name => kill.victim.faction
    raise ValidationError.new(source), "No ship called '#{kill.victim.ship}' exists" unless Item.exists? :name => kill.victim.ship
    raise ValidationError.new(source), "No moon called '#{kill.victim.moon}' exists" unless Moon.exists? :name => kill.victim.moon if kill.victim.moon
    
    kill.involved_parties = []
    
    involved_parties = source[/Involved parties:\n\n(((.+\n){8}\n|(.+\n){2}\n)*)/, 1] or raise ValidationError.new(source), "Involved parties malformed"
    involved_parties.split("\n\n").each_with_index do |snippet, i|
      
      lines = 0 and snippet.each_line { |line| lines += 1 }
      
      case lines
        
      when 8
        involved_party = Adam::Kill::InvolvedParty.new do |ip|
          ip.type                   = :PC
          ip.pilot                  = snippet[/Name: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Involved party #{i+1} pilot malformed"
          ip.security_status        = (snippet[/Security: ([\-\.0-9]+)/, 1] or raise ValidationError.new(source), "Involved party #{i+1} security malformed").to_f
          ip.corporation            = snippet[/Corp: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Involved party #{i+1} corporation malformed"
          ip.alliance               = snippet[/Alliance: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Involved party #{i+1} alliance malformed"
          ip.faction                = snippet[/Faction: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Involved party #{i+1} faction malformed"
          ip.ship                   = snippet[/Ship: (.+)/, 1] or raise ValidationError.new(source), "Involved party #{i+1} ship malformed"
          ip.weapon                 = snippet[/Weapon: (.+)/, 1] or raise ValidationError.new(source), "Involved party #{i+1} weapon malformed"
          ip.damage_done            = (snippet[/Damage Done: ([0-9]+)/, 1] or raise ValidationError.new(source), "Involved party #{i+1} damage malformed").to_i
          ip.final_blow             = snippet =~ /\(laid the final blow\)/ ? true : false
          
          # Convert alliance/faction from "unknown" or "none" to nil
          ip.alliance = nil if ip.alliance =~ /unknown|none/i
          ip.faction = nil if ip.faction =~ /unknown|none/i
        end
          
      when 2
        involved_party = Adam::Kill::InvolvedParty.new do |ip|
          ip.type                   = :NPC
          ip.ship                   = snippet[/Name: ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Involved party #{i+1} ship malformed"
          ip.damage_done            = (snippet[/Damage Done: ([0-9]+)/, 1] or raise ValidationError.new(source), "Involved party #{i+1} damage malformed").to_i
          ip.final_blow             = snippet =~ /\(laid the final blow\)/ ? true : false
          
          # Determine whether allegiance is a faction or a corporation
          allegiance = snippet[/Name: [^\/]+ \/ ([a-zA-Z0-9]{1}[a-zA-Z0-9'. -]{1,48}[a-zA-Z0-9.]{1})/, 1] or raise ValidationError.new(source), "Involved party #{i+1} allegiance malformed"
          if allegiance =~ /^(Caldari State|Minmatar Republic|Amarr Empire|Gallente Federation|Jove Empire|CONCORD Assembly|Ammatar Mandate|Khanid Kingdom|The Syndicate|Guristas Pirates|Angel Cartel|The Blood Raider Covenant|The InterBus|ORE|Thukker Tribe|The Servant Sisters of EVE|The Society|Mordu's Legion Command|Sansha's Nation|Serpentis)$/
            ip.faction = allegiance
          elsif allegiance == 'Unknown'
            ip.corporation = false
          else
            ip.corporation = allegiance
          end
        end
          
      end
      
      raise ValidationError.new(source), "No faction called '#{involved_party.faction}' exists" if involved_party.faction and !Faction.exists? :name => involved_party.faction
      raise ValidationError.new(source), "No ship called '#{involved_party.ship}' exists" unless Item.exists? :name => involved_party.ship
      
      kill.involved_parties << involved_party
      
    end
    
    kill.loot = []
    
    if source =~ /Destroyed items:/
      source[/Destroyed items:\n\n(((.+)\n?)*)/, 1].split("\n").each_with_index do |snippet, i|
        loot = Adam::Kill::Loot.new do |l|
          l.name       = snippet[/([^\(\)]+[^\s\(\)]{1})/, 1].gsub(/\b, Qty: \d+\b$/, "") or raise ValidationError.new(source), "Destroyed item #{i+1} name malformed"
          l.quantity   = snippet =~ /Qty: ([0-9]+)/ ? snippet[/Qty: ([0-9]+)/, 1].to_i : 1
          l.location   = :cargo_bay if snippet[/(Cargo)/]
          l.location   = :drone_bay if snippet[/(Drone Bay)/]
          l.location   = :implant   if snippet[/(Implant)/]
          l.location   = :copy      if snippet[/(Copy)/]
          l.dropped    = false
        end
        existing_loot = kill.loot.select { |el| el.name.eql?(loot.name) and el.location.eql?(loot.location) and el.dropped.eql?(loot.dropped) }[0]
        existing_loot ? existing_loot.quantity += loot.quantity : kill.loot << loot
      end
    end
    
    if source =~ /Dropped items:/
      source[/Dropped items:\n\n(((.+)\n?)*)/, 1].split("\n").each_with_index do |snippet, i|
        loot = Adam::Kill::Loot.new do |l|
          l.name       = snippet[/([^\(\)]+[^\s\(\)]{1})/, 1].gsub(/\b, Qty: \d+\b$/, "") or raise ValidationError.new(source), "Destroyed item #{i+1} name malformed"
          l.quantity   = snippet =~ /Qty: ([0-9]+)/ ? snippet[/Qty: ([0-9]+)/, 1].to_i : 1
          l.location   = :cargo_bay if snippet[/(Cargo)/]
          l.location   = :drone_bay if snippet[/(Drone Bay)/]
          l.location   = :implant   if snippet[/(Implant)/]
          l.location   = :copy      if snippet[/(Copy)/]
          l.dropped    = true
        end
        existing_loot = kill.loot.select { |el| el.name.eql?(loot.name) and el.location.eql?(loot.location) and el.dropped.eql?(loot.dropped) }[0]
        existing_loot ? existing_loot.quantity += loot.quantity : kill.loot << loot
      end
    end
    
  end
  
end