parent
							
								
									6b57d498b6
								
							
						
					
					
						commit
						228c594ca9
					
				
											
												Binary file not shown.
											
										
									
								
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,254 @@
 | 
				
			||||
[
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Rathian",
 | 
				
			||||
    "link": "/monster/001_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Apex Rathian",
 | 
				
			||||
    "link": "/monster/001_07.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Rathalos",
 | 
				
			||||
    "link": "/monster/002_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Apex Rathalos",
 | 
				
			||||
    "link": "/monster/002_07.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Khezu",
 | 
				
			||||
    "link": "/monster/003_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Basarios",
 | 
				
			||||
    "link": "/monster/004_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Diablos",
 | 
				
			||||
    "link": "/monster/007_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Apex Diablos",
 | 
				
			||||
    "link": "/monster/007_07.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Daimyo Hermitaur",
 | 
				
			||||
    "link": "/monster/019_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Shogun Ceanataur",
 | 
				
			||||
    "link": "/monster/020_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Rajang",
 | 
				
			||||
    "link": "/monster/023_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Furious Rajang",
 | 
				
			||||
    "link": "/monster/023_05.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Kushala Daora",
 | 
				
			||||
    "link": "/monster/024_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Chameleos",
 | 
				
			||||
    "link": "/monster/025_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Teostra",
 | 
				
			||||
    "link": "/monster/027_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Tigrex",
 | 
				
			||||
    "link": "/monster/032_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Nargacuga",
 | 
				
			||||
    "link": "/monster/037_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Barioth",
 | 
				
			||||
    "link": "/monster/042_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Barroth",
 | 
				
			||||
    "link": "/monster/044_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Royal Ludroth",
 | 
				
			||||
    "link": "/monster/047_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Great Baggi",
 | 
				
			||||
    "link": "/monster/054_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Zinogre",
 | 
				
			||||
    "link": "/monster/057_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Apex Zinogre",
 | 
				
			||||
    "link": "/monster/057_07.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Great Wroggi",
 | 
				
			||||
    "link": "/monster/059_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Arzuros",
 | 
				
			||||
    "link": "/monster/060_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Apex Arzuros",
 | 
				
			||||
    "link": "/monster/060_07.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Lagombi",
 | 
				
			||||
    "link": "/monster/061_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Volvidon",
 | 
				
			||||
    "link": "/monster/062_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Gore Magala",
 | 
				
			||||
    "link": "/monster/071_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Shagaru Magala",
 | 
				
			||||
    "link": "/monster/072_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Seregios",
 | 
				
			||||
    "link": "/monster/077_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Astalos",
 | 
				
			||||
    "link": "/monster/081_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Mizutsune",
 | 
				
			||||
    "link": "/monster/082_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Apex Mizutsune",
 | 
				
			||||
    "link": "/monster/082_07.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Crimson Glow Valstrax",
 | 
				
			||||
    "link": "/monster/086_05.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Magnamalo",
 | 
				
			||||
    "link": "/monster/089_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Scorned Magnamalo",
 | 
				
			||||
    "link": "/monster/089_05.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Bishaten",
 | 
				
			||||
    "link": "/monster/090_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Blood Orange Bishaten",
 | 
				
			||||
    "link": "/monster/090_01.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Aknosom",
 | 
				
			||||
    "link": "/monster/091_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Tetranadon",
 | 
				
			||||
    "link": "/monster/092_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Somnacanth",
 | 
				
			||||
    "link": "/monster/093_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Aurora Somnacanth",
 | 
				
			||||
    "link": "/monster/093_01.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Rakna-Kadaki",
 | 
				
			||||
    "link": "/monster/094_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Pyre Rakna-Kadaki",
 | 
				
			||||
    "link": "/monster/094_01.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Almudron",
 | 
				
			||||
    "link": "/monster/095_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Magma Almudron",
 | 
				
			||||
    "link": "/monster/095_01.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Wind Serpent Ibushi",
 | 
				
			||||
    "link": "/monster/096_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Goss Harag",
 | 
				
			||||
    "link": "/monster/097_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Great Izuchi",
 | 
				
			||||
    "link": "/monster/098_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Thunder Serpent Narwa",
 | 
				
			||||
    "link": "/monster/099_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Narwa the Allmother",
 | 
				
			||||
    "link": "/monster/099_05.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Anjanath",
 | 
				
			||||
    "link": "/monster/100_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Pukei-Pukei",
 | 
				
			||||
    "link": "/monster/102_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Kulu-Ya-Ku",
 | 
				
			||||
    "link": "/monster/107_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Jyuratodus",
 | 
				
			||||
    "link": "/monster/108_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Tobi-Kadachi",
 | 
				
			||||
    "link": "/monster/109_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Bazelgeuse",
 | 
				
			||||
    "link": "/monster/118_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Malzeno",
 | 
				
			||||
    "link": "/monster/132_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Lunagaron",
 | 
				
			||||
    "link": "/monster/133_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Garangolm",
 | 
				
			||||
    "link": "/monster/134_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Gaismagorm",
 | 
				
			||||
    "link": "/monster/135_00.html"
 | 
				
			||||
  },
 | 
				
			||||
  {
 | 
				
			||||
    "name": "Espinas",
 | 
				
			||||
    "link": "/monster/136_00.html"
 | 
				
			||||
  }
 | 
				
			||||
]
 | 
				
			||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								@ -0,0 +1,268 @@
 | 
				
			||||
#!/usr/bin/env python3
 | 
				
			||||
 | 
				
			||||
import os.path
 | 
				
			||||
import sys
 | 
				
			||||
import re
 | 
				
			||||
import json
 | 
				
			||||
import lxml.etree
 | 
				
			||||
 | 
				
			||||
import requests
 | 
				
			||||
 | 
				
			||||
#WTYPES = ["Great Sword", "Long Sword", "Sword and Shield", "Dual Blades", "Lance", "Gunlance", "Hammer"]
 | 
				
			||||
WTYPES = ["Great Sword", "Lance", "Hammer"]
 | 
				
			||||
 | 
				
			||||
WIDTH_RE = re.compile(r'width: *(\d+)%;')
 | 
				
			||||
 | 
				
			||||
PART_RE = re.compile(r'(.*) x(\d+)( Points)?')
 | 
				
			||||
 | 
				
			||||
# MR Bone 20 pts.
 | 
				
			||||
PART_RE_MR = re.compile(r'(.*) (\d+) +pts\.?')
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
"""
 | 
				
			||||
<div class="progress" style="max-width: 100%; min-width: 100px;"> 
 | 
				
			||||
      <div class="progress-bar danger-color-dark" style="width: 11%;">
 | 
				
			||||
          
 | 
				
			||||
      </div> 
 | 
				
			||||
      <div class="progress-bar warning-color-dark" style="width: 20%;">
 | 
				
			||||
          
 | 
				
			||||
      </div> 
 | 
				
			||||
      <div class="progress-bar warning-color" style="width: 12%;">
 | 
				
			||||
          
 | 
				
			||||
      </div> 
 | 
				
			||||
      <div class="progress-bar success-color" style="width: 0%;">
 | 
				
			||||
          
 | 
				
			||||
      </div> 
 | 
				
			||||
      <div class="progress-bar primary-color-dark" style="width: 0%;">
 | 
				
			||||
          
 | 
				
			||||
      </div> 
 | 
				
			||||
      <div class="progress-bar white" style="width: 0%;">
 | 
				
			||||
          
 | 
				
			||||
      </div> 
 | 
				
			||||
</div> 
 | 
				
			||||
"""
 | 
				
			||||
def parse_sharpness(div):
 | 
				
			||||
    values = []
 | 
				
			||||
    divs = div.xpath('div')
 | 
				
			||||
    for div in divs:
 | 
				
			||||
        style = div.get("style")
 | 
				
			||||
        m = WIDTH_RE.match(style)
 | 
				
			||||
        if m:
 | 
				
			||||
            values.append(int(m.group(1)))
 | 
				
			||||
 | 
				
			||||
    return values
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def parse_rampage(td):
 | 
				
			||||
    return td.xpath('ul/li/a/text()')
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def parse_crafting(td):
 | 
				
			||||
    materials = {}
 | 
				
			||||
    for li in td.xpath('ul/li'):
 | 
				
			||||
        atext = li.xpath('a/text()')
 | 
				
			||||
        litext = li.xpath('text()')
 | 
				
			||||
        if litext:
 | 
				
			||||
            litext = litext[0].strip()
 | 
				
			||||
        else:
 | 
				
			||||
            print("Unknown format: ", lxml.etree.tostring(td))
 | 
				
			||||
            return {}
 | 
				
			||||
 | 
				
			||||
        if litext.endswith('\xa0'):
 | 
				
			||||
            litext = litext.rstrip('\xa0')
 | 
				
			||||
        if litext.endswith('.'):
 | 
				
			||||
            litext = litext.rstrip('.')
 | 
				
			||||
 | 
				
			||||
        if litext.endswith('l'):
 | 
				
			||||
            litext = litext[:-1] + '1'
 | 
				
			||||
 | 
				
			||||
        if litext.startswith('+ '):
 | 
				
			||||
            atext += '+'
 | 
				
			||||
            litext = litext[2:]
 | 
				
			||||
 | 
				
			||||
        if litext.startswith('x'):
 | 
				
			||||
            litext = litext[1:]
 | 
				
			||||
 | 
				
			||||
        if atext:
 | 
				
			||||
            atext = atext[0].strip()
 | 
				
			||||
            if litext.endswith(" Points"):
 | 
				
			||||
                litext = litext.rstrip(" Points")
 | 
				
			||||
                atext += " Points"
 | 
				
			||||
            #print("atext '" + atext + "' '" + litext + "'")
 | 
				
			||||
            try:
 | 
				
			||||
                materials[atext] = clean_int(litext)
 | 
				
			||||
            except Exception as e:
 | 
				
			||||
                print("WARN: failed parsing ", atext, litext)
 | 
				
			||||
                if litext == 'l':
 | 
				
			||||
                    materials[atext] = 1
 | 
				
			||||
        elif litext.isdigit():
 | 
				
			||||
            materials['zenny'] = clean_int(litext)
 | 
				
			||||
        else:
 | 
				
			||||
            m = PART_RE.match(litext)
 | 
				
			||||
            if not m:
 | 
				
			||||
                m = PART_RE_MR.match(litext)
 | 
				
			||||
                if m:
 | 
				
			||||
                    materials[m.group(1) + ' Points'] = int(m.group(2))
 | 
				
			||||
            elif m.group(2):
 | 
				
			||||
                materials[m.group(1) + ' Points'] = int(m.group(2))
 | 
				
			||||
            else:
 | 
				
			||||
                materials[m.group(1)] = int(m.group(2))
 | 
				
			||||
    return materials
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def clean_text(t):
 | 
				
			||||
    t = t.strip()
 | 
				
			||||
    t = t.rstrip('\xa0')
 | 
				
			||||
    return t
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def clean_int(s):
 | 
				
			||||
    s = clean_text(s)
 | 
				
			||||
    if not s:
 | 
				
			||||
        return 0
 | 
				
			||||
    return int(s)
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def parse_element(td):
 | 
				
			||||
    #pp("td", td)
 | 
				
			||||
    etype = td.xpath('a/text()')
 | 
				
			||||
    if etype:
 | 
				
			||||
        values = td.xpath('./text()')
 | 
				
			||||
        if values:
 | 
				
			||||
            value = clean_int(values[0].strip())
 | 
				
			||||
            return dict(type=etype[0], attack=value)
 | 
				
			||||
    return dict(type=None, attack=None)
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def parse_rarity(td):
 | 
				
			||||
    text = td.xpath('.//text()')
 | 
				
			||||
    if text:
 | 
				
			||||
        parts = text[0].split()
 | 
				
			||||
        if len(parts) > 1:
 | 
				
			||||
            return clean_int(text[0].split()[1])
 | 
				
			||||
    return 8
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def parse_slots(td):
 | 
				
			||||
    slots = []
 | 
				
			||||
    for img in td.xpath('.//img'):
 | 
				
			||||
        title = img.get("title")
 | 
				
			||||
        if title and title.startswith('gem_'):
 | 
				
			||||
            parts = title.split("_")
 | 
				
			||||
            level = int(parts[2])
 | 
				
			||||
            slots.append(level)
 | 
				
			||||
    return slots
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def adjust_slots_rampage(data):
 | 
				
			||||
    if data['rarity'] >= 8:
 | 
				
			||||
        data['rampage_slot'] = data['slots'][-1]
 | 
				
			||||
        data['slots'] = data['slots'][:-1]
 | 
				
			||||
    else:
 | 
				
			||||
        data['rampage_slot'] = 0
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def gl_parse_tr(tr):
 | 
				
			||||
    data = {}
 | 
				
			||||
    cells = tr.xpath('td')
 | 
				
			||||
    #print(lxml.etree.tostring(cells[9]))
 | 
				
			||||
 | 
				
			||||
    # Name
 | 
				
			||||
    name = cells[0]
 | 
				
			||||
    #print(name)
 | 
				
			||||
    data['name'] = name.xpath('a/text()')[0]
 | 
				
			||||
    data['slots'] = parse_slots(name)
 | 
				
			||||
    data['sharpness'] = parse_sharpness(name.xpath('div')[0])
 | 
				
			||||
    data['attack'] = clean_int(cells[1].text)
 | 
				
			||||
    element = parse_element(cells[2])
 | 
				
			||||
    data['element'] = element['type']
 | 
				
			||||
    data['element_attack'] = element['attack']
 | 
				
			||||
    data['element_2'] = None
 | 
				
			||||
    data['element_2_attack'] = None
 | 
				
			||||
    data['affinity'] = clean_int(cells[3].text.rstrip('%'))
 | 
				
			||||
    data['defense'] = clean_int(cells[4].text)
 | 
				
			||||
    data['shot_type'] = cells[5].text
 | 
				
			||||
    data['level'] = clean_int(cells[6].text.split()[1])
 | 
				
			||||
    data['rarity'] = parse_rarity(cells[7])
 | 
				
			||||
    data['rampage_skills'] = parse_rampage(cells[8])
 | 
				
			||||
    data['crafting'] = parse_crafting(cells[9])
 | 
				
			||||
 | 
				
			||||
    adjust_slots_rampage(data)
 | 
				
			||||
 | 
				
			||||
    return data
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def default_parse_tr(tr):
 | 
				
			||||
    data = {}
 | 
				
			||||
    cells = tr.xpath('td')
 | 
				
			||||
    #print(lxml.etree.tostring(cells[9]))
 | 
				
			||||
 | 
				
			||||
    if len(cells) == 10:
 | 
				
			||||
        return gl_parse_tr(tr)
 | 
				
			||||
 | 
				
			||||
    #print("cels", [c.text for c in cells])
 | 
				
			||||
 | 
				
			||||
    # Name
 | 
				
			||||
    name = cells[0]
 | 
				
			||||
    data['name'] = name.xpath('a/text()')[0]
 | 
				
			||||
    data['slots'] = parse_slots(name)
 | 
				
			||||
    data['sharpness'] = parse_sharpness(name.xpath('div')[0])
 | 
				
			||||
    data['attack'] = clean_int(cells[1].text)
 | 
				
			||||
    element = parse_element(cells[2])
 | 
				
			||||
    data['element'] = element['type']
 | 
				
			||||
    data['element_attack'] = element['attack']
 | 
				
			||||
    data['element_2'] = None
 | 
				
			||||
    data['element_2_attack'] = None
 | 
				
			||||
    data['affinity'] = clean_int(cells[3].text.rstrip('%'))
 | 
				
			||||
    data['defense'] = clean_int(cells[4].text)
 | 
				
			||||
    data['rarity'] = parse_rarity(cells[5])
 | 
				
			||||
    data['rampage_skills'] = parse_rampage(cells[6])
 | 
				
			||||
    data['crafting'] = parse_crafting(cells[7])
 | 
				
			||||
 | 
				
			||||
    adjust_slots_rampage(data)
 | 
				
			||||
 | 
				
			||||
    return data
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def parse_fextralife_weapons(text):
 | 
				
			||||
    root = lxml.etree.HTML(text)
 | 
				
			||||
    weapons = []
 | 
				
			||||
 | 
				
			||||
    table = root.xpath('//div[@id="wiki-content-block"]//table')[0]
 | 
				
			||||
    rows = table.xpath('tbody/tr')
 | 
				
			||||
    #print("nrows", len(rows))
 | 
				
			||||
    for tr in rows:
 | 
				
			||||
        data = default_parse_tr(tr)
 | 
				
			||||
        weapons.append(data)
 | 
				
			||||
    return weapons
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def pp(name, e):
 | 
				
			||||
    if isinstance(e, list):
 | 
				
			||||
        for i, ei in enumerate(e):
 | 
				
			||||
            pp(name + "[" + str(i) + "]", ei)
 | 
				
			||||
    else:
 | 
				
			||||
        print(name, e.tag)
 | 
				
			||||
        print(lxml.etree.tostring(e, pretty_print=True))
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def _main():
 | 
				
			||||
    indir = sys.argv[1]
 | 
				
			||||
    outpath = sys.argv[2]
 | 
				
			||||
    weapon_list_all = []
 | 
				
			||||
    for wtype in WTYPES:
 | 
				
			||||
        print(wtype)
 | 
				
			||||
        fpath = os.path.join(indir, wtype + ".html")
 | 
				
			||||
        with open(fpath) as f:
 | 
				
			||||
            text = f.read()
 | 
				
			||||
        weapon_list = parse_fextralife_weapons(text)
 | 
				
			||||
        for w in weapon_list:
 | 
				
			||||
            w["wtype"] = wtype
 | 
				
			||||
        weapon_list_all.extend(weapon_list)
 | 
				
			||||
    with open(outpath, "w") as f:
 | 
				
			||||
        json.dump(weapon_list_all, f, indent=2)
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
if __name__ == '__main__':
 | 
				
			||||
    _main()
 | 
				
			||||
@ -0,0 +1,159 @@
 | 
				
			||||
#!/usr/bin/env python3
 | 
				
			||||
 | 
				
			||||
import sys
 | 
				
			||||
import os.path
 | 
				
			||||
import time
 | 
				
			||||
import re
 | 
				
			||||
import json
 | 
				
			||||
import lxml.etree
 | 
				
			||||
 | 
				
			||||
import requests
 | 
				
			||||
 | 
				
			||||
PART_HEADER_MAP = dict(Slash="Cut",
 | 
				
			||||
                       Impact="Impact",
 | 
				
			||||
                       Shot="Shot",
 | 
				
			||||
                       Fire="Fire",
 | 
				
			||||
                       Water="Water",
 | 
				
			||||
                       Ice="Ice",
 | 
				
			||||
                       Thunder="Thunder",
 | 
				
			||||
                       Dragon="Dragon")
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def _td_part_id(td):
 | 
				
			||||
    s = td.xpath('.//text()')[0].strip()
 | 
				
			||||
    if s.startswith("["):
 | 
				
			||||
        s = s[1:2]
 | 
				
			||||
    return int(s)
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def _td_part_break(td):
 | 
				
			||||
    text = td.text or ""
 | 
				
			||||
    text = text.strip()
 | 
				
			||||
    if text:
 | 
				
			||||
        m = re.match(r"\(x(\d+)\) (\d+)", text)
 | 
				
			||||
        print(text, m, m.group(1), m.group(2))
 | 
				
			||||
        return dict(count=int(m.group(1)), damage=int(m.group(2)))
 | 
				
			||||
    return dict(count=0, damage=0)
 | 
				
			||||
 | 
				
			||||
def _td_part_sever(td):
 | 
				
			||||
    text = td.text or ""
 | 
				
			||||
    text = text.strip()
 | 
				
			||||
    if text:
 | 
				
			||||
        m = re.match(r"\((\w+)\) (\d+)", text)
 | 
				
			||||
        return dict(type=m.group(1), damage=int(m.group(2)))
 | 
				
			||||
    return dict(type="", damage=0)
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def get_monster_data(link):
 | 
				
			||||
    hit_data = {}
 | 
				
			||||
    base = "https://mhrise.mhrice.info"
 | 
				
			||||
    url = base + link
 | 
				
			||||
    result = requests.get(url)
 | 
				
			||||
    root = lxml.etree.HTML(result.content)
 | 
				
			||||
    sections = root.xpath("//section")
 | 
				
			||||
    hit_table = None
 | 
				
			||||
    parts_table = None
 | 
				
			||||
    for section in sections:
 | 
				
			||||
        h2 = section.xpath('h2')
 | 
				
			||||
        if h2 and h2[0].text:
 | 
				
			||||
            if hit_table is None and h2[0].text.lower().startswith("hitzone"):
 | 
				
			||||
                hit_table = section.xpath('.//table')[0]
 | 
				
			||||
            elif parts_table is None and h2[0].text.lower().startswith("parts"):
 | 
				
			||||
                parts_table = section.xpath('.//table')[0]
 | 
				
			||||
    #pp("hit_table", hit_table)
 | 
				
			||||
    #pp("tr", hit_table.xpath('thead/tr'))
 | 
				
			||||
    header_cells = hit_table.xpath('thead/tr/th')
 | 
				
			||||
    header_names = [th.text for th in header_cells]
 | 
				
			||||
    #print("names", header_names)
 | 
				
			||||
    rows = hit_table.xpath('tbody/tr')
 | 
				
			||||
    part_id_name_map = {}
 | 
				
			||||
    for row in rows:
 | 
				
			||||
        if 'invalid' in row.attrib.get('class', ""):
 | 
				
			||||
            continue
 | 
				
			||||
        #pp("tr", row)
 | 
				
			||||
        cols = dict(zip(header_names, row.xpath('td')))
 | 
				
			||||
        name_td = cols["Name"]
 | 
				
			||||
        #pp("name_td", name_td)
 | 
				
			||||
        name_en_span = name_td.xpath('.//span[@lang="en"]/span')
 | 
				
			||||
        if not name_en_span:
 | 
				
			||||
            continue
 | 
				
			||||
        name = name_en_span[0].text
 | 
				
			||||
        #pp("part", cols["Part"].xpath('.//text()'))
 | 
				
			||||
        part_id = _td_part_id(cols["Part"])
 | 
				
			||||
        part_id_name_map[part_id] = name
 | 
				
			||||
        hit_data[name] = {}
 | 
				
			||||
        for k in PART_HEADER_MAP.keys():
 | 
				
			||||
            hit_data[name][PART_HEADER_MAP[k]] = int(cols[k].text)
 | 
				
			||||
    #print(hit_data)
 | 
				
			||||
 | 
				
			||||
    return hit_data
 | 
				
			||||
 | 
				
			||||
    # add break/sever data
 | 
				
			||||
    header_cells = parts_table.xpath('thead/tr/th')
 | 
				
			||||
    header_names = [th.text for th in header_cells]
 | 
				
			||||
    #print(header_names)
 | 
				
			||||
    rows = parts_table.xpath('tbody/tr')
 | 
				
			||||
    breaks = []
 | 
				
			||||
    for row in rows:
 | 
				
			||||
        if 'invalid' in row.attrib.get('class', ""):
 | 
				
			||||
            continue
 | 
				
			||||
        cols = dict(zip(header_names, row.xpath('td')))
 | 
				
			||||
        part_id = _td_part_id(cols["Part"])
 | 
				
			||||
        part_name = part_id_name_map[part_id]
 | 
				
			||||
        hit_data[part_name]["_stagger"] = int(cols["Stagger"].text)
 | 
				
			||||
        part_break = cols["Break"].text or ""
 | 
				
			||||
        part_sever = cols["Sever"].text or ""
 | 
				
			||||
        part_break = part_break.strip()
 | 
				
			||||
        part_sever = part_sever.strip()
 | 
				
			||||
        hit_data[part_name]["_break"] = _td_part_break(cols["Break"])
 | 
				
			||||
        hit_data[part_name]["_sever"] = _td_part_sever(cols["Sever"])
 | 
				
			||||
        if part_break or part_sever:
 | 
				
			||||
            breaks.append(part_name)
 | 
				
			||||
 | 
				
			||||
    hit_data["_breaks"] = breaks
 | 
				
			||||
    return hit_data
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def pp(name, e):
 | 
				
			||||
    if isinstance(e, list):
 | 
				
			||||
        for i, ei in enumerate(e):
 | 
				
			||||
            pp(name + "[" + str(i) + "]", ei)
 | 
				
			||||
    else:
 | 
				
			||||
        print(name, e.tag)
 | 
				
			||||
        print(lxml.etree.tostring(e, pretty_print=True))
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def get_monster_list():
 | 
				
			||||
    result = requests.get("https://mhrise.mhrice.info/monster.html")
 | 
				
			||||
    root = lxml.etree.HTML(result.content)
 | 
				
			||||
    monster_li = root.xpath('//ul[@id="slist-monster"]//li')
 | 
				
			||||
    monsters = []
 | 
				
			||||
    for li in monster_li:
 | 
				
			||||
        name = li.xpath('.//span[@lang="en"]/span')[0].text
 | 
				
			||||
        link = li.xpath('a')[0].attrib['href']
 | 
				
			||||
        monsters.append(dict(name=name, link=link))
 | 
				
			||||
    return monsters
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def _main():
 | 
				
			||||
    outdir = sys.argv[1]
 | 
				
			||||
    monster_list = get_monster_list()
 | 
				
			||||
    with open(os.path.join(outdir, "monster_list.json"), "w") as f:
 | 
				
			||||
        json.dump(monster_list, f, indent=2)
 | 
				
			||||
 | 
				
			||||
    monster_hitboxes = {}
 | 
				
			||||
    for m in monster_list:
 | 
				
			||||
        print(m["name"])
 | 
				
			||||
        try:
 | 
				
			||||
            monster_hitboxes[m["name"]] = get_monster_data(m["link"])
 | 
				
			||||
        except Exception as e:
 | 
				
			||||
            print("ERR: failed to parse hitzones for ", m["name"])
 | 
				
			||||
            print(repr(e), str(e))
 | 
				
			||||
        time.sleep(0.5)
 | 
				
			||||
 | 
				
			||||
    with open(os.path.join(outdir, "monster_hitboxes.json"), "w") as f:
 | 
				
			||||
        json.dump(monster_hitboxes, f, indent=2)
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
if __name__ == '__main__':
 | 
				
			||||
    _main()
 | 
				
			||||
@ -0,0 +1,352 @@
 | 
				
			||||
#!/usr/bin/env python3
 | 
				
			||||
 | 
				
			||||
import sys
 | 
				
			||||
import os.path
 | 
				
			||||
import time
 | 
				
			||||
import re
 | 
				
			||||
import json
 | 
				
			||||
from pprint import pprint
 | 
				
			||||
from collections import defaultdict
 | 
				
			||||
import lxml.etree
 | 
				
			||||
 | 
				
			||||
import requests
 | 
				
			||||
 | 
				
			||||
import _pathfix
 | 
				
			||||
 | 
				
			||||
from mhapi.util import WEAPON_TYPES
 | 
				
			||||
 | 
				
			||||
MAX_PER_TYPE = 100000
 | 
				
			||||
 | 
				
			||||
def pp(name, e):
 | 
				
			||||
    if isinstance(e, list):
 | 
				
			||||
        for i, ei in enumerate(e):
 | 
				
			||||
            pp(name + "[" + str(i) + "]", ei)
 | 
				
			||||
    else:
 | 
				
			||||
        print(name, e.tag)
 | 
				
			||||
        print(lxml.etree.tostring(e, pretty_print=True))
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def parse_sharpness(value_span):
 | 
				
			||||
    bar_span = value_span.xpath('.//span[@class="mh-sharpness-bar"]')[0]
 | 
				
			||||
    sharp_spans = bar_span.xpath('.//span')
 | 
				
			||||
    i = 0
 | 
				
			||||
    last_color_num = -1
 | 
				
			||||
    values = []
 | 
				
			||||
    values_plus = []
 | 
				
			||||
    for sharp_span in sharp_spans:
 | 
				
			||||
        # <span class="mh-sharpness mh-sharpness-color-0" style="left:0%;width:47.5%;"></span>
 | 
				
			||||
        attr_style = sharp_span.attrib["style"]
 | 
				
			||||
        attr_class = sharp_span.attrib["class"]
 | 
				
			||||
        classes = attr_class.split()
 | 
				
			||||
        half = False
 | 
				
			||||
        for class_name in classes:
 | 
				
			||||
            if class_name.startswith("mh-sharpness-color-"):
 | 
				
			||||
                color_num = int(class_name[-1])
 | 
				
			||||
            if class_name == "mh-sharpness-half":
 | 
				
			||||
                half = True
 | 
				
			||||
        styles = attr_style.split(";")
 | 
				
			||||
        for s in styles:
 | 
				
			||||
            s = s.strip()
 | 
				
			||||
            if not s:
 | 
				
			||||
                continue
 | 
				
			||||
            parts = s.split(":")
 | 
				
			||||
            if parts[0] == "width":
 | 
				
			||||
                value = int(2*float(parts[1].rstrip("%")))
 | 
				
			||||
                break
 | 
				
			||||
        if value == 0:
 | 
				
			||||
            continue
 | 
				
			||||
        if half:
 | 
				
			||||
            if not values_plus:
 | 
				
			||||
                values_plus = list(values)
 | 
				
			||||
            if color_num == last_color_num:
 | 
				
			||||
                values_plus[-1] += value
 | 
				
			||||
            else:
 | 
				
			||||
                values_plus.append(value)
 | 
				
			||||
        else:
 | 
				
			||||
            # fill in missing colors, if any
 | 
				
			||||
            while i < color_num:
 | 
				
			||||
                values.append(0)
 | 
				
			||||
                i += 1
 | 
				
			||||
            values.append(value)
 | 
				
			||||
        i += 1
 | 
				
			||||
        last_color_num = color_num
 | 
				
			||||
    return values, values_plus
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def _map_element(e):
 | 
				
			||||
    if e == "Bomb":
 | 
				
			||||
        return "Blast"
 | 
				
			||||
    if e == "Paralyze":
 | 
				
			||||
        return "Paralysis"
 | 
				
			||||
    return e
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def get_weapon_details(wtype, name, link):
 | 
				
			||||
    data = dict(wtype=wtype, name=name)
 | 
				
			||||
    url = "https://mhrise.mhrice.info" + link
 | 
				
			||||
    result = requests.get(url)
 | 
				
			||||
    root = lxml.etree.HTML(result.content)
 | 
				
			||||
 | 
				
			||||
    icon_div = root.xpath('//div[@class="mh-title-icon"]/div[@class="mh-colored-icon"]/div')[0]
 | 
				
			||||
    rarity_class = icon_div.attrib["class"]
 | 
				
			||||
    data["rarity"] = int(rarity_class.split("-")[-1])
 | 
				
			||||
 | 
				
			||||
    stat_div = root.xpath('//div[@class="mh-kvlist"]')[0]
 | 
				
			||||
    kvlist = stat_div.xpath('.//p[@class="mh-kv"]')
 | 
				
			||||
    for kv in kvlist:
 | 
				
			||||
        spans = kv.xpath('span')
 | 
				
			||||
        key = spans[0].text.strip().lower()
 | 
				
			||||
        if key in set(["attack", "affinity", "defense"]):
 | 
				
			||||
            value = spans[1].text
 | 
				
			||||
            value = value.rstrip("%")
 | 
				
			||||
            data[key.lower()] = int(value)
 | 
				
			||||
        elif key == "element":
 | 
				
			||||
            value_spans = spans[1].xpath("span")
 | 
				
			||||
            value = value_spans[0].text.strip()
 | 
				
			||||
            if value:
 | 
				
			||||
                parts = value.split()
 | 
				
			||||
                if parts[0] == "None":
 | 
				
			||||
                    data["element"] = None
 | 
				
			||||
                    data["element_attack"] = None
 | 
				
			||||
                else:
 | 
				
			||||
                    data["element"] = _map_element(parts[0])
 | 
				
			||||
                    data["element_attack"] = int(parts[1])
 | 
				
			||||
            if len(value_spans) > 1:
 | 
				
			||||
                value = value_spans[1].text.strip()
 | 
				
			||||
                parts = value.split()
 | 
				
			||||
                data["element_2"] = _map_element(parts[0])
 | 
				
			||||
                data["element_2_attack"] = int(parts[1])
 | 
				
			||||
            else:
 | 
				
			||||
                data["element_2"] = None
 | 
				
			||||
                data["element_2_attack"] = None
 | 
				
			||||
        elif key == "slot":
 | 
				
			||||
            # <img alt="A level-2 slot" class="mh-slot" src="/resources/slot_1.png">
 | 
				
			||||
            # <img alt="A level-4 slot" class="mh-slot-large" src="/resources/slot_3.png">
 | 
				
			||||
            slots = []
 | 
				
			||||
            value_span = spans[1]
 | 
				
			||||
            slot_imgs = value_span.xpath('.//span[@class="mh-slot-outer"]/img')
 | 
				
			||||
            for slot_img in slot_imgs:
 | 
				
			||||
                src = slot_img.attrib["src"]
 | 
				
			||||
                m = re.match(r".*/slot_(\d+)\.png", src)
 | 
				
			||||
                if m:
 | 
				
			||||
                    svalue = int(m.group(1)) + 1
 | 
				
			||||
                    slots.append(svalue)
 | 
				
			||||
            data["slots"] = slots
 | 
				
			||||
        elif key == "rampage slot":
 | 
				
			||||
            slots = []
 | 
				
			||||
            value_span = spans[1]
 | 
				
			||||
            slot_imgs = value_span.xpath('.//span[@class="mh-slot-outer"]/img')
 | 
				
			||||
            for slot_img in slot_imgs:
 | 
				
			||||
                src = slot_img.attrib["src"]
 | 
				
			||||
                m = re.match(r".*/slot_(\d+).png", src)
 | 
				
			||||
                if m:
 | 
				
			||||
                    svalue = int(m.group(1)) + 1
 | 
				
			||||
                    slots.append(svalue)
 | 
				
			||||
            data["rampage_slots"] = slots
 | 
				
			||||
        elif key == "sharpness":
 | 
				
			||||
            value_span = spans[1]
 | 
				
			||||
            sharp, sharp_plus = parse_sharpness(value_span)
 | 
				
			||||
            data["sharpness"] = sharp
 | 
				
			||||
            data["sharpness_plus"] = sharp_plus
 | 
				
			||||
        elif key == "bottle":
 | 
				
			||||
            value = spans[1].text.strip()
 | 
				
			||||
            if wtype == "Charge Blade":
 | 
				
			||||
                key = "phial"
 | 
				
			||||
                if value == "Power":
 | 
				
			||||
                    value = "Impact"
 | 
				
			||||
                if value == "StrongElement":
 | 
				
			||||
                    value = "Element"
 | 
				
			||||
            if wtype == "Switch Axe":
 | 
				
			||||
                key = "phial"
 | 
				
			||||
                parts = value.split()
 | 
				
			||||
                value = parts[0]
 | 
				
			||||
                if value == "StrongElement":
 | 
				
			||||
                    value = "Element"
 | 
				
			||||
                if value == "DownStamina":
 | 
				
			||||
                    value = "Exhaust"
 | 
				
			||||
                phial_num = int(parts[1])
 | 
				
			||||
                if phial_num > 0:
 | 
				
			||||
                    data["phial_value"] = phial_num
 | 
				
			||||
            data[key] = value
 | 
				
			||||
        elif key == "type":
 | 
				
			||||
            value = spans[1].text.strip()
 | 
				
			||||
            parts = value.split()
 | 
				
			||||
            value = parts[0]
 | 
				
			||||
            if len(parts) > 1:
 | 
				
			||||
                level = int(parts[1])
 | 
				
			||||
                data["shelling_level"] = level
 | 
				
			||||
            if wtype == "Gunlance":
 | 
				
			||||
                key = "shelling_type"
 | 
				
			||||
            if value == "Radial":
 | 
				
			||||
                value = "Long"
 | 
				
			||||
            elif value == "Diffusion":
 | 
				
			||||
                value = "Wide"
 | 
				
			||||
            data[key] = value
 | 
				
			||||
        elif key == "insect level":
 | 
				
			||||
            value = spans[1].text.strip()
 | 
				
			||||
            data["bug_level"] = int(value)
 | 
				
			||||
 | 
				
			||||
    sections = root.xpath("//section")
 | 
				
			||||
    craft_table = None
 | 
				
			||||
    for section in sections:
 | 
				
			||||
        h2 = section.xpath("h2/text()")
 | 
				
			||||
        if h2 and h2[0] == "Crafting":
 | 
				
			||||
            craft_table = section.xpath("div/table/tbody")[0]
 | 
				
			||||
            break
 | 
				
			||||
    if craft_table is not None:
 | 
				
			||||
        rows = craft_table.xpath("tr")
 | 
				
			||||
        for row in rows:
 | 
				
			||||
            cells = row.findall("td")
 | 
				
			||||
            craft_type = cells[0].text.strip()
 | 
				
			||||
            if craft_type.startswith("Forge"):
 | 
				
			||||
                zenny, comps = get_components(cells)
 | 
				
			||||
                data["creation_cost"] = zenny
 | 
				
			||||
                data["create_components"] = comps
 | 
				
			||||
            elif craft_type.startswith("Upgrade"):
 | 
				
			||||
                zenny, comps = get_components(cells)
 | 
				
			||||
                data["upgrade_cost"] = zenny
 | 
				
			||||
                data["upgrade_components"] = comps
 | 
				
			||||
 | 
				
			||||
    return data
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def get_components(cells):
 | 
				
			||||
    zenny = int(cells[1].text)
 | 
				
			||||
    cmat_text = cells[2].text
 | 
				
			||||
    components = {}
 | 
				
			||||
    if cmat_text != "-":
 | 
				
			||||
        cmat_name = cells[2].xpath('.//span[@lang="en"]/span')[0].text
 | 
				
			||||
        cmat_points_string = cells[2].xpath("span")[0].tail
 | 
				
			||||
        cmat_points = int(cmat_points_string.split(" ")[0])
 | 
				
			||||
        components[cmat_name] = cmat_points
 | 
				
			||||
    li_mats = cells[3].xpath("ul/li")
 | 
				
			||||
    for li in li_mats:
 | 
				
			||||
        count = int(li.text.strip().rstrip("x"))
 | 
				
			||||
        name = li.xpath('.//span[@lang="en"]/span')[0].text
 | 
				
			||||
        components[name] = count
 | 
				
			||||
    return (zenny, components)
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def get_rice_id(link):
 | 
				
			||||
    # /weapon/GreatSword_026.html
 | 
				
			||||
    fname_base, _ = os.path.splitext(os.path.basename(link))
 | 
				
			||||
    _, tail = fname_base.rsplit("_", maxsplit=1)
 | 
				
			||||
    return int(tail)
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def get_weapon_list(wtype, id_offset):
 | 
				
			||||
    if wtype == "Sword and Shield":
 | 
				
			||||
        ftype = "short_sword"
 | 
				
			||||
    elif wtype == "Hunting Horn":
 | 
				
			||||
        ftype = "horn"
 | 
				
			||||
    elif wtype == "Gunlance":
 | 
				
			||||
        ftype = "gun_lance"
 | 
				
			||||
    elif wtype == "Switch Axe":
 | 
				
			||||
        ftype = "slash_axe"
 | 
				
			||||
    elif wtype == "Charge Blade":
 | 
				
			||||
        ftype = "charge_axe"
 | 
				
			||||
    else:
 | 
				
			||||
        ftype = wtype.lower().replace(" ", "_")
 | 
				
			||||
    list_fname = ftype + ".html"
 | 
				
			||||
    result = requests.get("https://mhrise.mhrice.info/weapon/" + list_fname)
 | 
				
			||||
    root = lxml.etree.HTML(result.content)
 | 
				
			||||
    weapon_tree_li = root.xpath('//div[@class="mh-weapon-tree"]//li')
 | 
				
			||||
    weapons = []
 | 
				
			||||
    seen = set()
 | 
				
			||||
    for li in weapon_tree_li:
 | 
				
			||||
        listack = [li]
 | 
				
			||||
        name_stack = [None]
 | 
				
			||||
        while listack:
 | 
				
			||||
            current_li = listack.pop()
 | 
				
			||||
            parent_name = name_stack.pop()
 | 
				
			||||
 | 
				
			||||
            a = current_li.xpath('a[@class="mh-icon-text"]')[0]
 | 
				
			||||
            sublists = current_li.xpath('ul/li')
 | 
				
			||||
 | 
				
			||||
            name = a.xpath('.//span[@lang="en"]/span')[0].text
 | 
				
			||||
            link = a.attrib['href']
 | 
				
			||||
 | 
				
			||||
            name_stack.extend([name] * len(sublists))
 | 
				
			||||
            listack.extend(sublists)
 | 
				
			||||
 | 
				
			||||
            if link in seen:
 | 
				
			||||
                print("WARN: Duplicate ", name, link)
 | 
				
			||||
                continue
 | 
				
			||||
            seen.add(link)
 | 
				
			||||
 | 
				
			||||
            id_ = get_rice_id(link) + id_offset
 | 
				
			||||
            final = (len(sublists) == 0)
 | 
				
			||||
            wdata = dict(name=name, link=link, _id=id_, parent_name=parent_name, final=final)
 | 
				
			||||
            weapons.append(wdata)
 | 
				
			||||
 | 
				
			||||
    return weapons
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def test_details():
 | 
				
			||||
    tests = [
 | 
				
			||||
        ("Great Sword", "Sinister Shadowblade+", "/weapon/GreatSword_403.html"),
 | 
				
			||||
        ("Great Sword", "Redwing Claymore I", "/weapon/GreatSword_068.html"),
 | 
				
			||||
        ("Great Sword", "Defender Great Sword I", "/weapon/GreatSword_132.html"),
 | 
				
			||||
        ("Great Sword", "Kamura Warrior Cleaver", "/weapon/GreatSword_300.html"),
 | 
				
			||||
        ("Dual Blades", "Blood Wind Skards+", "/weapon/DualBlades_319.html"),
 | 
				
			||||
        ("Switch Axe", "Arzuros Jubilax", "/weapon/SlashAxe_323.html"),
 | 
				
			||||
        ("Switch Axe", "Leave-Taker+", "/weapon/SlashAxe_307.html"),
 | 
				
			||||
        ("Insect Glaive", "Fine Kamura Glaive", "/weapon/InsectGlaive_302.html"),
 | 
				
			||||
    ]
 | 
				
			||||
    for t in tests:
 | 
				
			||||
        print(t)
 | 
				
			||||
        d = get_weapon_details(*t)
 | 
				
			||||
        pprint(d)
 | 
				
			||||
        print()
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
def _main():
 | 
				
			||||
    weapons_type_name_map = defaultdict(dict)
 | 
				
			||||
    weapons_data = []
 | 
				
			||||
 | 
				
			||||
    outdir = sys.argv[1]
 | 
				
			||||
    outfile = os.path.join(outdir, "weapon_list.json")
 | 
				
			||||
    if os.path.exists(outfile):
 | 
				
			||||
        print("Loading existing data from ", outfile)
 | 
				
			||||
        with open(outfile) as f:
 | 
				
			||||
            old_data = json.load(f)
 | 
				
			||||
            for d in old_data:
 | 
				
			||||
                wtype_name_map = weapons_type_name_map[d["wtype"]]
 | 
				
			||||
                if d["name"] in wtype_name_map:
 | 
				
			||||
                    print("Removing duplicate ", d["wtype"], d["name"])
 | 
				
			||||
                    continue
 | 
				
			||||
                wtype_name_map[d["name"]] = d
 | 
				
			||||
 | 
				
			||||
    for itype, wtype in enumerate(WEAPON_TYPES):
 | 
				
			||||
        wtype_name_map = weapons_type_name_map[wtype]
 | 
				
			||||
        weapons = get_weapon_list(wtype, (itype+1) * MAX_PER_TYPE)
 | 
				
			||||
        if not weapons:
 | 
				
			||||
            print("WARN: no weapons of type", wtype)
 | 
				
			||||
            continue
 | 
				
			||||
        name_id_map = {}
 | 
				
			||||
        for w in weapons:
 | 
				
			||||
            # always re-calculate IDs
 | 
				
			||||
            name_id_map[w["name"]] = w["_id"]
 | 
				
			||||
            if w["parent_name"]:
 | 
				
			||||
                w["parent_id"] = name_id_map[w["parent_name"]]
 | 
				
			||||
            else:
 | 
				
			||||
                w["parent_id"] = None
 | 
				
			||||
            data = wtype_name_map.get(w["name"])
 | 
				
			||||
            if data is not None:
 | 
				
			||||
                print("UP ", wtype, w["_id"], w["name"], w["link"])
 | 
				
			||||
                data.update(w)
 | 
				
			||||
                weapons_data.append(data)
 | 
				
			||||
                continue
 | 
				
			||||
            print("ADD", wtype, w["_id"], w["name"], w["link"])
 | 
				
			||||
            data = get_weapon_details(wtype, w["name"], w["link"])
 | 
				
			||||
            data.update(w)
 | 
				
			||||
            weapons_data.append(data)
 | 
				
			||||
            time.sleep(0.5)
 | 
				
			||||
 | 
				
			||||
    with open(os.path.join(outdir, "weapon_list.json"), "w") as f:
 | 
				
			||||
        json.dump(weapons_data, f, indent=2)
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
if __name__ == '__main__':
 | 
				
			||||
    #test_details()
 | 
				
			||||
    _main()
 | 
				
			||||
@ -0,0 +1,36 @@
 | 
				
			||||
## -*- coding: utf-8 -*-
 | 
				
			||||
 | 
				
			||||
<!DOCTYPE html>
 | 
				
			||||
<html>
 | 
				
			||||
 | 
				
			||||
<head>
 | 
				
			||||
<title>Poogie's Calculator - ${self.title()}</title>
 | 
				
			||||
<meta charset="utf-8" />
 | 
				
			||||
<!-- Include meta tag to ensure proper rendering and touch zooming -->
 | 
				
			||||
<meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||
 | 
				
			||||
<script src="/js/jquery.min.js"></script>
 | 
				
			||||
 | 
				
			||||
<!--link rel="stylesheet" href="/css/jquery-ui.min.css" /-->
 | 
				
			||||
<!--script src="/js/jquery-ui.min.js"></script-->
 | 
				
			||||
 | 
				
			||||
<script src="/js/common.js"></script>
 | 
				
			||||
 | 
				
			||||
</head>
 | 
				
			||||
 | 
				
			||||
<link rel="stylesheet" href="/css/poogie.css">
 | 
				
			||||
 | 
				
			||||
<style>
 | 
				
			||||
  body {
 | 
				
			||||
    font-size: 1em;
 | 
				
			||||
    line-height: 1.3;
 | 
				
			||||
    font-family: sans-serif;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  img.icon { width: 20px; height: 20px; }
 | 
				
			||||
</style>
 | 
				
			||||
 | 
				
			||||
<body>
 | 
				
			||||
<h1><%block name="title"/></h1>
 | 
				
			||||
${self.body()}
 | 
				
			||||
</body>
 | 
				
			||||
@ -0,0 +1,67 @@
 | 
				
			||||
<%inherit file="base.html" />
 | 
				
			||||
 | 
				
			||||
<div id="poogie-header">
 | 
				
			||||
 <div class="poogie-header-content">
 | 
				
			||||
  <div class="poogie-header-title">Menu</div>
 | 
				
			||||
 </div>
 | 
				
			||||
</div>
 | 
				
			||||
 | 
				
			||||
<div id="poogie-content">
 | 
				
			||||
<div class="pure-menu">
 | 
				
			||||
<ul class="pure-menu-list">
 | 
				
			||||
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link"
 | 
				
			||||
       href="skilltrees-en.html">Skill Trees</a>
 | 
				
			||||
  </li>
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link" href="hunterarts.html">Hunter Arts</a>
 | 
				
			||||
  </li>
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link" href="monsters-en.html">Monsters</a>
 | 
				
			||||
  </li>
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link"
 | 
				
			||||
       href="monster-titles.html">Monster Titles</a>
 | 
				
			||||
  </li>
 | 
				
			||||
 | 
				
			||||
  <li class="pure-menu-heading poogie-menu-heading">Items</li>
 | 
				
			||||
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link"
 | 
				
			||||
       href="items-en.html">Items (Usable, Gatherable)</a>
 | 
				
			||||
  </li>
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link"
 | 
				
			||||
       href="items-carve-en.html">Monster Carves</a>
 | 
				
			||||
  </li>
 | 
				
			||||
 | 
				
			||||
  <li class="pure-menu-heading poogie-menu-heading">Old Sites (searchable but slow load)</li>
 | 
				
			||||
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link"
 | 
				
			||||
       href="site-jqueryui.html">Version 2 (home menu navigation)</a>
 | 
				
			||||
  </li>
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link"
 | 
				
			||||
       href="site-jqueryui-tabbed.html">Version 1 (tabbed navigation)</a>
 | 
				
			||||
  </li>
 | 
				
			||||
 | 
				
			||||
  <li class="pure-menu-heading poogie-menu-heading">Acknowledgments / Sources</li>
 | 
				
			||||
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link"
 | 
				
			||||
       href="http://monsterhunter.wikia.com/wiki/MHX"
 | 
				
			||||
       >Monster Hunter X Wiki (Wikia)</a>
 | 
				
			||||
  </li>
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link"
 | 
				
			||||
       href="https://github.com/kamegami13/MonsterHunter4UDatabase">MonsterHunter4UDatabase</a>
 | 
				
			||||
  </li>
 | 
				
			||||
  <li class="pure-menu-item poogie-menu-item">
 | 
				
			||||
    <a class="pure-menu-link"
 | 
				
			||||
       href="http://creativecommons.org/licenses/by-sa/3.0/">License CC-BY-SA</a>
 | 
				
			||||
  </li>
 | 
				
			||||
</ul>
 | 
				
			||||
</div>
 | 
				
			||||
</div>
 | 
				
			||||
@ -0,0 +1,312 @@
 | 
				
			||||
## -*- coding: utf-8 -*-
 | 
				
			||||
 | 
				
			||||
<!DOCTYPE html>
 | 
				
			||||
<html>
 | 
				
			||||
 | 
				
			||||
<head>
 | 
				
			||||
<title>Poogie's Calculator: ${monster} v${village_stars} g${guild_stars}</title>
 | 
				
			||||
<meta charset="utf-8" />
 | 
				
			||||
<!-- Include meta tag to ensure proper rendering and touch zooming -->
 | 
				
			||||
<meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||
 | 
				
			||||
<script src="/js/jquery.min.js"></script>
 | 
				
			||||
 | 
				
			||||
<link rel="stylesheet" href="/css/jquery-ui.min.css" />
 | 
				
			||||
<script src="/js/jquery-ui.min.js"></script>
 | 
				
			||||
 | 
				
			||||
<script src="/js/common.js"></script>
 | 
				
			||||
 | 
				
			||||
<link rel="stylesheet" href="/css/poogie.css">
 | 
				
			||||
 | 
				
			||||
<style>
 | 
				
			||||
  body {
 | 
				
			||||
    font-size: 1em;
 | 
				
			||||
    line-height: 1.3;
 | 
				
			||||
    font-family: sans-serif;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  img.icon { width: 20px; height: 20px; }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar {
 | 
				
			||||
      border: 1px #a9a9a9 solid;
 | 
				
			||||
      min-width: 82px;
 | 
				
			||||
      height: 10px;
 | 
				
			||||
      background-color: #a9a9a9;
 | 
				
			||||
      float: left;
 | 
				
			||||
      clear: both;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar span {
 | 
				
			||||
      display: inline-block;
 | 
				
			||||
      height: 100%;
 | 
				
			||||
      float: left;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .red {
 | 
				
			||||
      background-color: #C00C38 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .orange {
 | 
				
			||||
      background-color: #E85018 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .yellow {
 | 
				
			||||
      background-color: #F0C830 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .green {
 | 
				
			||||
      background-color: #58D000 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .blue {
 | 
				
			||||
      background-color: #3068E8 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .white {
 | 
				
			||||
      background-color: #F0F0F0 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .purple {
 | 
				
			||||
      background-color: #c3c !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  #sharpness_popup {
 | 
				
			||||
      position: absolute;
 | 
				
			||||
      display: none;
 | 
				
			||||
      border: 1px solid;
 | 
				
			||||
      background: rgba(204, 204, 204, 0.9);
 | 
				
			||||
      z-index: 10;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
  .sharpness-box {
 | 
				
			||||
    float: left;
 | 
				
			||||
    width: 10px;
 | 
				
			||||
    height: 10px;
 | 
				
			||||
    margin: 1px;
 | 
				
			||||
    border: 1px solid rgba(0, 0, 0, .2);
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Red {
 | 
				
			||||
    background-color: #C00C38 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Orange {
 | 
				
			||||
    background-color: #E85018 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Yellow {
 | 
				
			||||
    background-color: #F0C830 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Green {
 | 
				
			||||
    background-color: #58D000 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Blue {
 | 
				
			||||
    background-color: #3068E8 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .White {
 | 
				
			||||
    background-color: #F0F0F0 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Purple {
 | 
				
			||||
    background-color: #c3c !important;
 | 
				
			||||
  }
 | 
				
			||||
</style>
 | 
				
			||||
 | 
				
			||||
<script type="text/javascript">
 | 
				
			||||
  function load_monster_damage(form) {
 | 
				
			||||
     var url = "/mh4u/damage/" + $("#monster").val()
 | 
				
			||||
             + "/v" + $("#village_stars").val()
 | 
				
			||||
             + "g" + $("#guild_stars").val()
 | 
				
			||||
             + "/" + $("#weapon_type").val() + ".html";
 | 
				
			||||
     window.location.href = url;
 | 
				
			||||
  }
 | 
				
			||||
  $(document).ready(function(){
 | 
				
			||||
    setup_monster_autocomplete("mh4u", "#monster");
 | 
				
			||||
    $( "#village_stars" ).spinner({
 | 
				
			||||
      spin: function(event, ui) {
 | 
				
			||||
        if (${monster_stars["Village"]} == 0) {
 | 
				
			||||
          if (ui.value != 0) {
 | 
				
			||||
            return false;
 | 
				
			||||
          }
 | 
				
			||||
        } else if (ui.value < ${monster_stars["Village"]}) {
 | 
				
			||||
          return false;
 | 
				
			||||
        } else if (ui.value > 10) {
 | 
				
			||||
          return false;
 | 
				
			||||
        }
 | 
				
			||||
      }
 | 
				
			||||
    });
 | 
				
			||||
    $( "#guild_stars" ).spinner({
 | 
				
			||||
      spin: function(event, ui) {
 | 
				
			||||
        if (${monster_stars["Guild"]} == 0) {
 | 
				
			||||
          if (ui.value != 0) {
 | 
				
			||||
            return false;
 | 
				
			||||
          }
 | 
				
			||||
        } else if (ui.value < ${monster_stars["Guild"]}) {
 | 
				
			||||
          return false;
 | 
				
			||||
        } else if (ui.value > 10) {
 | 
				
			||||
          return false;
 | 
				
			||||
        }
 | 
				
			||||
      }
 | 
				
			||||
    });
 | 
				
			||||
  });
 | 
				
			||||
</script>
 | 
				
			||||
 | 
				
			||||
</head>
 | 
				
			||||
 | 
				
			||||
<body>
 | 
				
			||||
<form action="javascript:void(0);" onsubmit="load_monster_damage(this)">
 | 
				
			||||
  <span>
 | 
				
			||||
    <input id="monster" name="monster" type="text" size="20"
 | 
				
			||||
               value="${monster}" /></td>
 | 
				
			||||
    <select id="weapon_type" name="weapon_type">
 | 
				
			||||
     % for wname in weapon_types:
 | 
				
			||||
       % if wname == weapon_type:
 | 
				
			||||
        <option value="${wname}" selected="selected">${wname}</option>
 | 
				
			||||
       % else:
 | 
				
			||||
        <option value="${wname}">${wname}</option>
 | 
				
			||||
       % endif
 | 
				
			||||
     % endfor
 | 
				
			||||
    </select>
 | 
				
			||||
  </span>
 | 
				
			||||
  <span>
 | 
				
			||||
    <label for="village_stars">Village:</label>
 | 
				
			||||
    <input id="village_stars" name="village_stars" value="${village_stars}"
 | 
				
			||||
           style="width: 18px">
 | 
				
			||||
    <label for="guild_stars">Guild:</label>
 | 
				
			||||
    <input id="guild_stars" name="guild_stars" value="${guild_stars}"
 | 
				
			||||
           style="width: 18px">
 | 
				
			||||
    <input type="submit" value="Go" />
 | 
				
			||||
  </span>
 | 
				
			||||
</form>
 | 
				
			||||
 | 
				
			||||
<p>Breaks: ${", ".join(monster_breaks)}</p>
 | 
				
			||||
 | 
				
			||||
% if monster_damage.alt_state != "Default":
 | 
				
			||||
<p>Alternate state: ${monster_damage.alt_state}</p>
 | 
				
			||||
% endif
 | 
				
			||||
 | 
				
			||||
<table border="1" cellpadding="2" cellspacing="0">
 | 
				
			||||
  <tr>
 | 
				
			||||
    <th colspan="6">Weapon</th>
 | 
				
			||||
    <th>Avg</th>
 | 
				
			||||
    % for part in part_names:
 | 
				
			||||
      % if part in monster_breaks:
 | 
				
			||||
    <th style="background: pink;">${part}</th>
 | 
				
			||||
      % else:
 | 
				
			||||
    <th>${part}</th>
 | 
				
			||||
      % endif
 | 
				
			||||
    % endfor
 | 
				
			||||
  </tr>
 | 
				
			||||
 | 
				
			||||
  % for dtype in damage_types:
 | 
				
			||||
  <% max_damage = monster_damage.max(dtype) %>
 | 
				
			||||
  <% avg_damage = monster_damage.avg(dtype) %>
 | 
				
			||||
  <% alt_avg_damage = monster_damage.alt_avg(dtype) %>
 | 
				
			||||
  <tr style="border: 0px;">
 | 
				
			||||
    <td colspan="6" align="left">
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="dtype"
 | 
				
			||||
           src="/img/${dtype.capitalize()}.png" />
 | 
				
			||||
      ${dtype}
 | 
				
			||||
    </td>
 | 
				
			||||
    <td align="right">
 | 
				
			||||
      % if avg_damage > 0 or alt_avg_damage > 0:
 | 
				
			||||
      ${round(avg_damage, 1)}
 | 
				
			||||
        % if alt_avg_damage != avg_damage:
 | 
				
			||||
        (${round(alt_avg_damage, 1)})
 | 
				
			||||
        % endif
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="dtype"
 | 
				
			||||
           src="/img/${dtype.capitalize()}.png" />
 | 
				
			||||
      % else:
 | 
				
			||||
       
 | 
				
			||||
      % endif
 | 
				
			||||
    </td>
 | 
				
			||||
    % for part_name, part in monster_damage.items():
 | 
				
			||||
    <% bgcolor = "lightyellow" if (part[dtype] > 0 and part[dtype] == max_damage) else "white" %>
 | 
				
			||||
      % if part.state_diff(dtype) != 0:
 | 
				
			||||
    <td align="right" style="background: ${bgcolor}">
 | 
				
			||||
      % if part[dtype] > 0 or part.get_alt_state(dtype) > 0:
 | 
				
			||||
      ${part[dtype]} (${part.get_alt_state(dtype)})
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="dtype"
 | 
				
			||||
           src="/img/${dtype.capitalize()}.png" />
 | 
				
			||||
      % else:
 | 
				
			||||
       
 | 
				
			||||
      % endif
 | 
				
			||||
    </td>
 | 
				
			||||
      % else:
 | 
				
			||||
    <td align="right" style="background: ${bgcolor}">
 | 
				
			||||
      % if part[dtype] > 0:
 | 
				
			||||
      ${part[dtype]}
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="dtype"
 | 
				
			||||
           src="/img/${dtype.capitalize()}.png" />
 | 
				
			||||
      % else:
 | 
				
			||||
       
 | 
				
			||||
      %endif
 | 
				
			||||
    </td>
 | 
				
			||||
      % endif
 | 
				
			||||
    % endfor
 | 
				
			||||
  </tr>
 | 
				
			||||
  % endfor
 | 
				
			||||
 | 
				
			||||
  % for weapon in weapon_names:
 | 
				
			||||
  <% damage = weapon_damage_map[weapon] %>
 | 
				
			||||
  <% affinity = str(int(damage.affinity)) + "%" if damage.affinity else " " %>
 | 
				
			||||
  <% avg = damage.uniform(0.0) %>
 | 
				
			||||
  <% avg_break = damage.uniform(1.0) %>
 | 
				
			||||
  <tr style="border: 0px;">
 | 
				
			||||
    <td align="left">
 | 
				
			||||
      <a href="/mh4u/weaponplanner.html?weapon=${weapon | u}">${weapon}</a>
 | 
				
			||||
    </td>
 | 
				
			||||
    <td align="right">${int(damage.attack)}</td>
 | 
				
			||||
    <td align="right">${affinity}</td>
 | 
				
			||||
    <td align="center" title="${damage.weapon.sharpness}">
 | 
				
			||||
      <div class="sharpness-box ${damage.sharpness_name}" />
 | 
				
			||||
    </td>
 | 
				
			||||
    % if damage.eattack > 0:
 | 
				
			||||
    <td align="right">
 | 
				
			||||
      ${int(damage.eattack)}
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="${damage.etype}"
 | 
				
			||||
           src="/img/${damage.etype}.png" />
 | 
				
			||||
    </td>
 | 
				
			||||
    % else:
 | 
				
			||||
    <td> </td>
 | 
				
			||||
    % endif
 | 
				
			||||
    % if damage.eattack2 > 0:
 | 
				
			||||
    <td align="right">
 | 
				
			||||
      ${int(damage.eattack2)}
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="${damage.etype2}"
 | 
				
			||||
           src="/img/${damage.etype2}.png" />
 | 
				
			||||
    </td>
 | 
				
			||||
    % else:
 | 
				
			||||
    <td> </td>
 | 
				
			||||
    % endif
 | 
				
			||||
 | 
				
			||||
    <td align="right">
 | 
				
			||||
      ${round(avg, 1)}
 | 
				
			||||
      % if avg != avg_break:
 | 
				
			||||
      (${round(avg_break, 1)})
 | 
				
			||||
      % endif
 | 
				
			||||
    </td>
 | 
				
			||||
    % for part in part_names:
 | 
				
			||||
    <% bgcolor = "yellow" if damage[part].average() == part_max_damage[part] else "white" %>
 | 
				
			||||
    <td align="right" style="background: ${bgcolor};">
 | 
				
			||||
      ${int(damage[part].total)}
 | 
				
			||||
    % if damage[part].total_break != damage[part].total:
 | 
				
			||||
      (${int(damage[part].total_break)})
 | 
				
			||||
    % endif
 | 
				
			||||
    </td>
 | 
				
			||||
    % endfor
 | 
				
			||||
  </tr>
 | 
				
			||||
  % endfor
 | 
				
			||||
</table>
 | 
				
			||||
<div id="sharpness_popup"></div>
 | 
				
			||||
</body>
 | 
				
			||||
@ -0,0 +1,279 @@
 | 
				
			||||
## -*- coding: utf-8 -*-
 | 
				
			||||
 | 
				
			||||
<!DOCTYPE html>
 | 
				
			||||
<html>
 | 
				
			||||
 | 
				
			||||
<head>
 | 
				
			||||
<title>Poogie's Calculator: ${monster} r${rarity}</title>
 | 
				
			||||
<meta charset="utf-8" />
 | 
				
			||||
<!-- Include meta tag to ensure proper rendering and touch zooming -->
 | 
				
			||||
<meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||
 | 
				
			||||
<script src="/js/jquery.min.js"></script>
 | 
				
			||||
 | 
				
			||||
<link rel="stylesheet" href="/css/jquery-ui.min.css" />
 | 
				
			||||
<script src="/js/jquery-ui.min.js"></script>
 | 
				
			||||
 | 
				
			||||
<script src="/js/common.js"></script>
 | 
				
			||||
 | 
				
			||||
<link rel="stylesheet" href="/css/poogie.css">
 | 
				
			||||
 | 
				
			||||
<style>
 | 
				
			||||
  body {
 | 
				
			||||
    font-size: 1em;
 | 
				
			||||
    line-height: 1.3;
 | 
				
			||||
    font-family: sans-serif;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  img.icon { width: 20px; height: 20px; }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar {
 | 
				
			||||
      border: 1px #a9a9a9 solid;
 | 
				
			||||
      min-width: 82px;
 | 
				
			||||
      height: 10px;
 | 
				
			||||
      background-color: #a9a9a9;
 | 
				
			||||
      float: left;
 | 
				
			||||
      clear: both;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar span {
 | 
				
			||||
      display: inline-block;
 | 
				
			||||
      height: 100%;
 | 
				
			||||
      float: left;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .red {
 | 
				
			||||
      background-color: #C00C38 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .orange {
 | 
				
			||||
      background-color: #E85018 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .yellow {
 | 
				
			||||
      background-color: #F0C830 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .green {
 | 
				
			||||
      background-color: #58D000 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .blue {
 | 
				
			||||
      background-color: #3068E8 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .white {
 | 
				
			||||
      background-color: #F0F0F0 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .sharpness-bar .purple {
 | 
				
			||||
      background-color: #c3c !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  #sharpness_popup {
 | 
				
			||||
      position: absolute;
 | 
				
			||||
      display: none;
 | 
				
			||||
      border: 1px solid;
 | 
				
			||||
      background: rgba(204, 204, 204, 0.9);
 | 
				
			||||
      z-index: 10;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
  .sharpness-box {
 | 
				
			||||
    float: left;
 | 
				
			||||
    width: 10px;
 | 
				
			||||
    height: 10px;
 | 
				
			||||
    margin: 1px;
 | 
				
			||||
    border: 1px solid rgba(0, 0, 0, .2);
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Red {
 | 
				
			||||
    background-color: #C00C38 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Orange {
 | 
				
			||||
    background-color: #E85018 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Yellow {
 | 
				
			||||
    background-color: #F0C830 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Green {
 | 
				
			||||
    background-color: #58D000 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Blue {
 | 
				
			||||
    background-color: #3068E8 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .White {
 | 
				
			||||
    background-color: #F0F0F0 !important;
 | 
				
			||||
  }
 | 
				
			||||
 | 
				
			||||
  .Purple {
 | 
				
			||||
    background-color: #c3c !important;
 | 
				
			||||
  }
 | 
				
			||||
</style>
 | 
				
			||||
 | 
				
			||||
<script type="text/javascript">
 | 
				
			||||
  function load_monster_damage(form) {
 | 
				
			||||
     var url = "/mhr/damage/" + $("#monster").val()
 | 
				
			||||
             + "/r" + $("#rarity").val()
 | 
				
			||||
             + "/" + $("#weapon_type").val() + ".html";
 | 
				
			||||
     window.location.href = url;
 | 
				
			||||
  }
 | 
				
			||||
  $(document).ready(function(){
 | 
				
			||||
    setup_monster_autocomplete("mhr", "#monster");
 | 
				
			||||
    $( "#rarity" ).spinner({
 | 
				
			||||
      spin: function(event, ui) {
 | 
				
			||||
        if (ui.value > 10) {
 | 
				
			||||
          return false;
 | 
				
			||||
        }
 | 
				
			||||
      }
 | 
				
			||||
    });
 | 
				
			||||
  });
 | 
				
			||||
</script>
 | 
				
			||||
 | 
				
			||||
</head>
 | 
				
			||||
 | 
				
			||||
<body>
 | 
				
			||||
<form action="javascript:void(0);" onsubmit="load_monster_damage(this)">
 | 
				
			||||
  <span>
 | 
				
			||||
    <input id="monster" name="monster" type="text" size="20"
 | 
				
			||||
               value="${monster}" /></td>
 | 
				
			||||
    <select id="weapon_type" name="weapon_type">
 | 
				
			||||
     % for wname in weapon_types:
 | 
				
			||||
       % if wname == weapon_type:
 | 
				
			||||
        <option value="${wname}" selected="selected">${wname}</option>
 | 
				
			||||
       % else:
 | 
				
			||||
        <option value="${wname}">${wname}</option>
 | 
				
			||||
       % endif
 | 
				
			||||
     % endfor
 | 
				
			||||
    </select>
 | 
				
			||||
  </span>
 | 
				
			||||
  <span>
 | 
				
			||||
    <label for="rarity">Rarity:</label>
 | 
				
			||||
    <input id="rarity" name="rarity" value="${rarity}"
 | 
				
			||||
           style="width: 18px">
 | 
				
			||||
    <input type="submit" value="Go" />
 | 
				
			||||
  </span>
 | 
				
			||||
</form>
 | 
				
			||||
 | 
				
			||||
<table border="1" cellpadding="2" cellspacing="0">
 | 
				
			||||
  <tr>
 | 
				
			||||
    <th colspan="6">Weapon</th>
 | 
				
			||||
    <th>Avg</th>
 | 
				
			||||
    % for part in part_names:
 | 
				
			||||
    <th>${part}</th>
 | 
				
			||||
    % endfor
 | 
				
			||||
  </tr>
 | 
				
			||||
 | 
				
			||||
  % for dtype in damage_types:
 | 
				
			||||
  <% max_damage = monster_damage.max(dtype) %>
 | 
				
			||||
  <% avg_damage = monster_damage.avg(dtype) %>
 | 
				
			||||
  <% alt_avg_damage = monster_damage.alt_avg(dtype) %>
 | 
				
			||||
  <tr style="border: 0px;">
 | 
				
			||||
    <td colspan="6" align="left">
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="dtype"
 | 
				
			||||
           src="/img/${dtype.capitalize()}.png" />
 | 
				
			||||
      ${dtype}
 | 
				
			||||
    </td>
 | 
				
			||||
    <td align="right">
 | 
				
			||||
      % if avg_damage > 0 or alt_avg_damage > 0:
 | 
				
			||||
      ${round(avg_damage, 1)}
 | 
				
			||||
        % if alt_avg_damage != avg_damage:
 | 
				
			||||
        (${round(alt_avg_damage, 1)})
 | 
				
			||||
        % endif
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="dtype"
 | 
				
			||||
           src="/img/${dtype.capitalize()}.png" />
 | 
				
			||||
      % else:
 | 
				
			||||
       
 | 
				
			||||
      % endif
 | 
				
			||||
    </td>
 | 
				
			||||
    % for part_name, part in monster_damage.items():
 | 
				
			||||
    <% bgcolor = "lightyellow" if (part[dtype] > 0 and part[dtype] == max_damage) else "white" %>
 | 
				
			||||
      % if part.state_diff(dtype) != 0:
 | 
				
			||||
    <td align="right" style="background: ${bgcolor}">
 | 
				
			||||
      % if part[dtype] > 0 or part.get_alt_state(dtype) > 0:
 | 
				
			||||
      ${part[dtype]} (${part.get_alt_state(dtype)})
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="dtype"
 | 
				
			||||
           src="/img/${dtype.capitalize()}.png" />
 | 
				
			||||
      % else:
 | 
				
			||||
       
 | 
				
			||||
      % endif
 | 
				
			||||
    </td>
 | 
				
			||||
      % else:
 | 
				
			||||
    <td align="right" style="background: ${bgcolor}">
 | 
				
			||||
      % if part[dtype] > 0:
 | 
				
			||||
      ${part[dtype]}
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="dtype"
 | 
				
			||||
           src="/img/${dtype.capitalize()}.png" />
 | 
				
			||||
      % else:
 | 
				
			||||
       
 | 
				
			||||
      %endif
 | 
				
			||||
    </td>
 | 
				
			||||
      % endif
 | 
				
			||||
    % endfor
 | 
				
			||||
  </tr>
 | 
				
			||||
  % endfor
 | 
				
			||||
 | 
				
			||||
  % for weapon in weapon_names:
 | 
				
			||||
  <% damage = weapon_damage_map[weapon] %>
 | 
				
			||||
  <% affinity = str(int(damage.affinity)) + "%" if damage.affinity else " " %>
 | 
				
			||||
  <% avg = damage.uniform(0.0) %>
 | 
				
			||||
  <% avg_break = damage.uniform(1.0) %>
 | 
				
			||||
  <tr style="border: 0px;">
 | 
				
			||||
    <td align="left">
 | 
				
			||||
      <a href="/mhr/weaponplanner.html?weapon=${weapon | u}">${weapon}</a>
 | 
				
			||||
    </td>
 | 
				
			||||
    <td align="right">${int(damage.attack)}</td>
 | 
				
			||||
    <td align="right">${affinity}</td>
 | 
				
			||||
    <td align="center" title="${damage.weapon.sharpness}">
 | 
				
			||||
      <div class="sharpness-box ${damage.sharpness_name}" />
 | 
				
			||||
    </td>
 | 
				
			||||
    % if damage.eattack > 0:
 | 
				
			||||
    <td align="right">
 | 
				
			||||
      ${int(damage.eattack)}
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="${damage.etype}"
 | 
				
			||||
           src="/img/${damage.etype}.png" />
 | 
				
			||||
    </td>
 | 
				
			||||
    % else:
 | 
				
			||||
    <td> </td>
 | 
				
			||||
    % endif
 | 
				
			||||
    % if damage.eattack2 > 0:
 | 
				
			||||
    <td align="right">
 | 
				
			||||
      ${int(damage.eattack2)}
 | 
				
			||||
      <img style="height:.8em"
 | 
				
			||||
           title="${damage.etype2}"
 | 
				
			||||
           src="/img/${damage.etype2}.png" />
 | 
				
			||||
    </td>
 | 
				
			||||
    % else:
 | 
				
			||||
    <td> </td>
 | 
				
			||||
    % endif
 | 
				
			||||
 | 
				
			||||
    <td align="right">
 | 
				
			||||
      ${round(avg, 1)}
 | 
				
			||||
      % if avg != avg_break:
 | 
				
			||||
      (${round(avg_break, 1)})
 | 
				
			||||
      % endif
 | 
				
			||||
    </td>
 | 
				
			||||
    % for part in part_names:
 | 
				
			||||
    <% bgcolor = "yellow" if damage[part].average() == part_max_damage[part] else "white" %>
 | 
				
			||||
    <td align="right" style="background: ${bgcolor};">
 | 
				
			||||
      ${int(damage[part].total)}
 | 
				
			||||
    % if damage[part].total_break != damage[part].total:
 | 
				
			||||
      (${int(damage[part].total_break)})
 | 
				
			||||
    % endif
 | 
				
			||||
    </td>
 | 
				
			||||
    % endfor
 | 
				
			||||
  </tr>
 | 
				
			||||
  % endfor
 | 
				
			||||
</table>
 | 
				
			||||
<div id="sharpness_popup"></div>
 | 
				
			||||
</body>
 | 
				
			||||
| 
		 After Width: | Height: | Size: 15 KiB  | 
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
| 
		 After Width: | Height: | Size: 2.0 KiB  | 
@ -0,0 +1,345 @@
 | 
				
			||||
<html>
 | 
				
			||||
<head>
 | 
				
			||||
  <title>Poogie's Weapon List (Rise)</title>
 | 
				
			||||
 | 
				
			||||
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
 | 
				
			||||
 | 
				
			||||
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
 | 
				
			||||
  <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
 | 
				
			||||
 | 
				
			||||
  <script type="text/javascript" src="../js/ejs_production.js"></script>
 | 
				
			||||
 | 
				
			||||
  <script type="text/javascript" src="../js/common.js"></script>
 | 
				
			||||
 | 
				
			||||
  <style>
 | 
				
			||||
      label {
 | 
				
			||||
          font-weight: bold;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      body {
 | 
				
			||||
          font-family: sans, sans-serif;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      td.plus {
 | 
				
			||||
          background-color: LightCyan;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      td.minus {
 | 
				
			||||
          background-color: LightPink;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      td.num {
 | 
				
			||||
          text-align: right;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      /*@media (max-width: 600) {*/
 | 
				
			||||
      .flexbox {
 | 
				
			||||
          display: flex;
 | 
				
			||||
          flex-direction: row;
 | 
				
			||||
          flex-wrap: wrap;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar {
 | 
				
			||||
          border: 1px #a9a9a9 solid;
 | 
				
			||||
          min-width: 90px;
 | 
				
			||||
          height: 7px;
 | 
				
			||||
          background-color: #a9a9a9;
 | 
				
			||||
          float: left;
 | 
				
			||||
          clear: both;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar span {
 | 
				
			||||
          display: inline-block;
 | 
				
			||||
          height: 100%;
 | 
				
			||||
          float: left;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .red {
 | 
				
			||||
          background-color: #C00C38 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .orange {
 | 
				
			||||
          background-color: #E85018 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .yellow {
 | 
				
			||||
          background-color: #F0C830 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .green {
 | 
				
			||||
          background-color: #58D000 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .blue {
 | 
				
			||||
          background-color: #3068E8 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .white {
 | 
				
			||||
          background-color: #F0F0F0 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .purple {
 | 
				
			||||
          background-color: #c3c !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      #sharpness_popup {
 | 
				
			||||
          position: absolute;
 | 
				
			||||
          display: none;
 | 
				
			||||
          border: 1px solid;
 | 
				
			||||
          background: rgba(204, 204, 204, 0.9);
 | 
				
			||||
          z-index: 10;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      #cp_div {
 | 
				
			||||
          display: none;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
  </style>
 | 
				
			||||
 | 
				
			||||
  <script type="text/javascript">
 | 
				
			||||
    var WEAPON_LIST = null;
 | 
				
			||||
 | 
				
			||||
    $.ajax({
 | 
				
			||||
        url: "../jsonapi/mhr/weapon/_all.json",
 | 
				
			||||
        async: false,
 | 
				
			||||
        dataType: "json",
 | 
				
			||||
        success: function (data) {
 | 
				
			||||
            WEAPON_LIST = data;
 | 
				
			||||
            console.log("weapon count " + WEAPON_LIST.length);
 | 
				
			||||
        }
 | 
				
			||||
    });
 | 
				
			||||
 | 
				
			||||
    var template_row = new EJS({ url: "/templates/weaponrow-rise.ejs" });
 | 
				
			||||
 | 
				
			||||
    $(document).ready(function(){
 | 
				
			||||
        init_page();
 | 
				
			||||
 | 
				
			||||
        $("#sharpness_popup").on("click", function(evt) {
 | 
				
			||||
            $(this).html("").offset({top:0, left:0}).hide();
 | 
				
			||||
        });
 | 
				
			||||
 | 
				
			||||
        $("#weapon_table").on("click", "#sharpness_td", function(evt) {
 | 
				
			||||
            var td_obj = $(evt.currentTarget);
 | 
				
			||||
            var offset = td_obj.offset();
 | 
				
			||||
            var sharpness = td_obj.data("sharpness");
 | 
				
			||||
            $("#sharpness_popup").html(sharpness).offset(offset).show();
 | 
				
			||||
        });
 | 
				
			||||
    });
 | 
				
			||||
 | 
				
			||||
    function init_page() {
 | 
				
			||||
        var qs = load_qs();
 | 
				
			||||
        $(window).on("popstate", function(e) {
 | 
				
			||||
            var oe = e.originalEvent;
 | 
				
			||||
            if (oe.state !== null) {
 | 
				
			||||
                console.log("popState:" + JSON.stringify(oe.state));
 | 
				
			||||
                update_weapon_list(oe.state);
 | 
				
			||||
            }
 | 
				
			||||
        });
 | 
				
			||||
        $("#search").click(function(evt) {
 | 
				
			||||
            var state = get_ui_state();
 | 
				
			||||
            save_state(state);
 | 
				
			||||
            update_weapon_list(state);
 | 
				
			||||
        });
 | 
				
			||||
 | 
				
			||||
        if (qs) {
 | 
				
			||||
            update_weapon_list(qs);
 | 
				
			||||
        }
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function load_qs() {
 | 
				
			||||
        if ($.QueryString["weapon_type"]) {
 | 
				
			||||
            load_state($.QueryString);
 | 
				
			||||
            return $.QueryString;
 | 
				
			||||
        }
 | 
				
			||||
        return null;
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function get_ui_state() {
 | 
				
			||||
        return { "weapon_type": $("#weapon_type").val(),
 | 
				
			||||
                 "weapon_element": $("#weapon_element").val(),
 | 
				
			||||
                 "weapon_final": $("#weapon_final").is(":checked"),
 | 
				
			||||
                 "weapon_name_text": $("#weapon_name_text").val(),
 | 
				
			||||
                 "weapon_rarity": $("#weapon_rarity").val() };
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function load_state(state) {
 | 
				
			||||
        $("#weapon_type").val(state["weapon_type"]);
 | 
				
			||||
        $("#weapon_element").val(state["weapon_element"]);
 | 
				
			||||
        if (typeof final == "string") {
 | 
				
			||||
            final = final.toLowerCase();
 | 
				
			||||
            state["weapon_final"] = (final == "true" || final == "1");
 | 
				
			||||
        }
 | 
				
			||||
        $("#weapon_final").prop("checked", state["weapon_final"]);
 | 
				
			||||
        $("#weapon_name_text").val(state["weapon_name_text"]);
 | 
				
			||||
        $("#weapon_rarity").val(state["weapon_rarity"]);
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function save_state(state, replace) {
 | 
				
			||||
        var url = "weaponlist.html?" + encode_qs(state);
 | 
				
			||||
        if (replace) {
 | 
				
			||||
            window.history.replaceState(state, "", url);
 | 
				
			||||
        } else {
 | 
				
			||||
            window.history.pushState(state, "", url);
 | 
				
			||||
        }
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function weapon_predicate(state, weapon_data) {
 | 
				
			||||
        var weapon_type = state["weapon_type"];
 | 
				
			||||
        var weapon_element = state["weapon_element"];
 | 
				
			||||
        var final_only = state["weapon_final"];
 | 
				
			||||
        var rarity = state["weapon_rarity"];
 | 
				
			||||
        var weapon_names = state["weapon_name_text"].split("|");
 | 
				
			||||
 | 
				
			||||
        if (final_only && !Boolean(weapon_data["final"])) {
 | 
				
			||||
            return false;
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        if (rarity != "Any" && weapon_data["rarity"] > rarity) {
 | 
				
			||||
            return false;
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        if (weapon_type != "All" && weapon_type != weapon_data["wtype"]) {
 | 
				
			||||
            return false;
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        if (weapon_element != "All"
 | 
				
			||||
        &&  weapon_element != weapon_data["element"]
 | 
				
			||||
        &&  weapon_element != weapon_data["element_2"]
 | 
				
			||||
        &&  weapon_element != weapon_data["awaken"]
 | 
				
			||||
        &&  weapon_element != weapon_data["phial"]) {
 | 
				
			||||
            if (weapon_element != "None"
 | 
				
			||||
            ||  weapon_data["element"] != null
 | 
				
			||||
            || weapon_data["awaken"] != null) {
 | 
				
			||||
                return false;
 | 
				
			||||
            }
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        if (weapon_names && !list_match(weapon_names, [weapon_data["name"]])) {
 | 
				
			||||
            return false;
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        return true;
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function list_match(needles, string_list) {
 | 
				
			||||
        var found = false;
 | 
				
			||||
        for (var i=0; i<string_list.length; i++) {
 | 
				
			||||
            for (var j=0; j<needles.length; j++) {
 | 
				
			||||
                if (string_list[i].search(needles[j]) >= 0) {
 | 
				
			||||
                    found = true;
 | 
				
			||||
                    break;
 | 
				
			||||
                }
 | 
				
			||||
                if (found) {
 | 
				
			||||
                    break;
 | 
				
			||||
                }
 | 
				
			||||
            }
 | 
				
			||||
        }
 | 
				
			||||
        return found;
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function update_weapon_list(state) {
 | 
				
			||||
        var match_count = 0;
 | 
				
			||||
        console.log("updating weapon list: " + JSON.stringify(state));
 | 
				
			||||
        var results = [];
 | 
				
			||||
        $.each(WEAPON_LIST, function(i, weapon_data) {
 | 
				
			||||
            if (weapon_predicate(state, weapon_data)) {
 | 
				
			||||
                weapon_data["id"] = i;
 | 
				
			||||
                weapon_data["sharpness_width"] = 0.4;
 | 
				
			||||
                match_count += 1;
 | 
				
			||||
                set_sharpness_titles(weapon_data);
 | 
				
			||||
                set_bow_values(weapon_data);
 | 
				
			||||
                weapon_data["wtype_short"] =
 | 
				
			||||
                          WEAPON_TYPE_ABBR[weapon_data["wtype"]];
 | 
				
			||||
                weapon_data["ELEMENT_ABBR"] = ELEMENT_ABBR;
 | 
				
			||||
                var html = template_row.render(weapon_data);
 | 
				
			||||
                results.push([weapon_data, html]);
 | 
				
			||||
            }
 | 
				
			||||
        });
 | 
				
			||||
        results.sort(function (a, b) {
 | 
				
			||||
            avals = get_weapon_sort_values(a[0]);
 | 
				
			||||
            bvals = get_weapon_sort_values(b[0]);
 | 
				
			||||
            return cmp_arrays(bvals, avals);
 | 
				
			||||
        });
 | 
				
			||||
        $("#weapon_table").empty();
 | 
				
			||||
        $.each(results, function(i, pair) {
 | 
				
			||||
            $("#weapon_table").append(pair[1]);
 | 
				
			||||
        });
 | 
				
			||||
        console.log("match count: " + match_count);
 | 
				
			||||
 | 
				
			||||
    }
 | 
				
			||||
  </script>
 | 
				
			||||
</head>
 | 
				
			||||
<body>
 | 
				
			||||
<div>
 | 
				
			||||
  <table>
 | 
				
			||||
  <tr>
 | 
				
			||||
    <td><label for="weapon_type"
 | 
				
			||||
               title="Only show weapons of this type"
 | 
				
			||||
        >Type:</label></td>
 | 
				
			||||
    <td><select id="weapon_type">
 | 
				
			||||
        <option value="All">All</option>
 | 
				
			||||
        <option value="Great Sword">Great Sword</option>
 | 
				
			||||
        <option value="Long Sword">Long Sword</option>
 | 
				
			||||
        <option value="Sword and Shield">Sword and Shield</option>
 | 
				
			||||
        <option value="Dual Blades">Dual Blades</option>
 | 
				
			||||
        <option value="Hammer">Hammer</option>
 | 
				
			||||
        <option value="Hunting Horn">Hunting Horn</option>
 | 
				
			||||
        <option value="Lance">Lance</option>
 | 
				
			||||
        <option value="Gunlance">Gunlance</option>
 | 
				
			||||
        <option value="Switch Axe">Switch Axe</option>
 | 
				
			||||
        <option value="Charge Blade">Charge Blade</option>
 | 
				
			||||
        <option value="Insect Glaive">Insect Glaive</option>
 | 
				
			||||
        <!--option value="Light Bowgun">Light Bowgun</option-->
 | 
				
			||||
        <!--option value="Heavy Bowgun">Heavy Bowgun</option-->
 | 
				
			||||
        <option value="Bow">Bow</option>
 | 
				
			||||
    </select></td>
 | 
				
			||||
    <td><label for="weapon_element"
 | 
				
			||||
               title="Only show weapons with this element (native or requiring awaken)"
 | 
				
			||||
        >Element:</label></td>
 | 
				
			||||
    <td><select id="weapon_element">
 | 
				
			||||
        <option value="All">All</option>
 | 
				
			||||
        <option value="None">None</option>
 | 
				
			||||
        <option value="Fire">Fire</option>
 | 
				
			||||
        <option value="Water">Water</option>
 | 
				
			||||
        <option value="Thunder">Thunder</option>
 | 
				
			||||
        <option value="Ice">Ice</option>
 | 
				
			||||
        <option value="Dragon">Dragon</option>
 | 
				
			||||
        <option value="Poison">Poison</option>
 | 
				
			||||
        <option value="Paralysis">Paralysis</option>
 | 
				
			||||
        <option value="Sleep">Sleep</option>
 | 
				
			||||
        <option value="Blast">Blast</option>
 | 
				
			||||
    </select></td>
 | 
				
			||||
    <td><label>Rarity:</label>
 | 
				
			||||
    <select id="weapon_rarity">
 | 
				
			||||
     <option value="Any">*</option>
 | 
				
			||||
     <option value="1">1</option>
 | 
				
			||||
     <option value="2">2</option>
 | 
				
			||||
     <option value="3">3</option>
 | 
				
			||||
     <option value="4">4</option>
 | 
				
			||||
     <option value="5">5</option>
 | 
				
			||||
     <option value="6">6</option>
 | 
				
			||||
     <option value="7">7</option>
 | 
				
			||||
     <option value="8">8</option>
 | 
				
			||||
     <option value="9">9</option>
 | 
				
			||||
     <option value="10">10</option>
 | 
				
			||||
    </select></td>
 | 
				
			||||
    <td><label for="weapon_final"
 | 
				
			||||
               title="Only show weapons with no furthur upgrades"
 | 
				
			||||
        >Final?</label></td>
 | 
				
			||||
    <td><input id="weapon_final" type="checkbox" /></td>
 | 
				
			||||
    <td><button id="search">Search</button></td>
 | 
				
			||||
  </tr>
 | 
				
			||||
  <tr>
 | 
				
			||||
    <td colspan="8">
 | 
				
			||||
      <label for="weapon_name_text"
 | 
				
			||||
             title="Show only weapons with a match in the name. List of strings separated by '|' (vertical bar)."
 | 
				
			||||
             >Name:</label>
 | 
				
			||||
      <input id="weapon_name_text" size="15" />
 | 
				
			||||
    </td>
 | 
				
			||||
  </tr>
 | 
				
			||||
  </table>
 | 
				
			||||
</div>
 | 
				
			||||
<table id="weapon_table">
 | 
				
			||||
</table>
 | 
				
			||||
<div id="sharpness_popup"></div>
 | 
				
			||||
</body>
 | 
				
			||||
@ -0,0 +1,284 @@
 | 
				
			||||
<html>
 | 
				
			||||
<head>
 | 
				
			||||
  <title>Poogie's Weapon Planner (Rise)</title>
 | 
				
			||||
 | 
				
			||||
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
 | 
				
			||||
 | 
				
			||||
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
 | 
				
			||||
  <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
 | 
				
			||||
 | 
				
			||||
  <script type="text/javascript" src="/js/ejs_production.js"></script>
 | 
				
			||||
 | 
				
			||||
  <script type="text/javascript" src="/js/common.js"></script>
 | 
				
			||||
 | 
				
			||||
  <style>
 | 
				
			||||
      label {
 | 
				
			||||
          font-weight: bold;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      body {
 | 
				
			||||
          font-family: sans, sans-serif;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      td.plus {
 | 
				
			||||
          background-color: LightCyan;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      td.minus {
 | 
				
			||||
          background-color: LightPink;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      td.num {
 | 
				
			||||
          text-align: right;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      /*@media (max-width: 600) {*/
 | 
				
			||||
      .flexbox {
 | 
				
			||||
          display: flex;
 | 
				
			||||
          flex-direction: row;
 | 
				
			||||
          flex-wrap: wrap;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar {
 | 
				
			||||
          border: 1px #d3d3d3 solid;
 | 
				
			||||
          min-width: 92px;
 | 
				
			||||
          height: 10px;
 | 
				
			||||
          background-color: #d3d3d3;
 | 
				
			||||
          float: left;
 | 
				
			||||
          clear: both;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar span {
 | 
				
			||||
          display: inline-block;
 | 
				
			||||
          height: 100%;
 | 
				
			||||
          float: left;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .red {
 | 
				
			||||
          background-color: #C00C38 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .orange {
 | 
				
			||||
          background-color: #E85018 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .yellow {
 | 
				
			||||
          background-color: #F0C830 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .green {
 | 
				
			||||
          background-color: #58D000 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .blue {
 | 
				
			||||
          background-color: #3068E8 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .white {
 | 
				
			||||
          background-color: #F0F0F0 !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
      .sharpness-bar .purple {
 | 
				
			||||
          background-color: #c3c !important;
 | 
				
			||||
      }
 | 
				
			||||
 | 
				
			||||
  </style>
 | 
				
			||||
 | 
				
			||||
  <script type="text/javascript">
 | 
				
			||||
    var DATA_PATH = "/jsonapi/mhr/";
 | 
				
			||||
 | 
				
			||||
    var template_path = new EJS({ url: "/templates/weaponpath.ejs" });
 | 
				
			||||
    var template_stats = new EJS({ url: "/templates/weaponstats.ejs" });
 | 
				
			||||
 | 
				
			||||
    $(document).ready(function(){
 | 
				
			||||
        setup_weapon_autocomplete("#weapon", autocomplete_predicate,
 | 
				
			||||
                                  init_page, update_search);
 | 
				
			||||
    });
 | 
				
			||||
 | 
				
			||||
    function init_page() {
 | 
				
			||||
        load_qs();
 | 
				
			||||
        $("#search").click(update_search);
 | 
				
			||||
        $(window).on("popstate", function(e) {
 | 
				
			||||
            var oe = e.originalEvent;
 | 
				
			||||
            if (oe.state !== null) {
 | 
				
			||||
                console.log("popState:" + JSON.stringify(oe.state));
 | 
				
			||||
                $("#weapon_type").val(oe.state["weapon_type"]);
 | 
				
			||||
                $("#weapon_type").change();
 | 
				
			||||
                show_trees(oe.state["weapon"]);
 | 
				
			||||
            }
 | 
				
			||||
        });
 | 
				
			||||
        $("#weapon_type").change(function(evt) {
 | 
				
			||||
            update_weapon_autocomplete("#weapon", autocomplete_predicate,
 | 
				
			||||
                                       update_search);
 | 
				
			||||
            $("#weapon").val("");
 | 
				
			||||
        });
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function load_qs() {
 | 
				
			||||
        var wtype = $.QueryString["weapon_type"];
 | 
				
			||||
        var weapon = $.QueryString["weapon"];
 | 
				
			||||
        if (!wtype) {
 | 
				
			||||
            wtype = "All";
 | 
				
			||||
        }
 | 
				
			||||
        $("#weapon_type").val(wtype);
 | 
				
			||||
        $("#weapon_type").change();
 | 
				
			||||
        if (weapon) {
 | 
				
			||||
            show_trees(weapon);
 | 
				
			||||
            console.log("replaceState: " + weapon);
 | 
				
			||||
            save_state(get_state(), true);
 | 
				
			||||
        }
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function get_state() {
 | 
				
			||||
        return { "weapon": $("#weapon").val(),
 | 
				
			||||
                 "weapon_type": $("#weapon_type").val() };
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function save_state(state, replace) {
 | 
				
			||||
        var url = "/mhr/weaponplanner.html?" + encode_qs(state);
 | 
				
			||||
        if (replace) {
 | 
				
			||||
            window.history.replaceState(state, "", url);
 | 
				
			||||
        } else {
 | 
				
			||||
            window.history.pushState(state, "", url);
 | 
				
			||||
        }
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function autocomplete_predicate(weapon_data) {
 | 
				
			||||
        var weapon_type = $("#weapon_type").val();
 | 
				
			||||
 | 
				
			||||
        if (weapon_type != "All" && weapon_type != weapon_data["wtype"]) {
 | 
				
			||||
            return false;
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        return true;
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function update_search() {
 | 
				
			||||
        var weapon_name = $("#weapon").val();
 | 
				
			||||
 | 
				
			||||
        if (!weapon_name) return;
 | 
				
			||||
 | 
				
			||||
        if (window.history.state
 | 
				
			||||
            && window.history.state["weapon"] == weapon_name) {
 | 
				
			||||
            console.log("weapon not changed, skipping update");
 | 
				
			||||
            return;
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        show_trees(weapon_name);
 | 
				
			||||
        console.log("pushState: " + weapon_name);
 | 
				
			||||
        save_state(get_state(), false);
 | 
				
			||||
    }
 | 
				
			||||
 | 
				
			||||
    function show_trees(weapon_name) {
 | 
				
			||||
        console.log("show_trees '" + weapon_name + "'");
 | 
				
			||||
        if (!weapon_name) return;
 | 
				
			||||
        weapon_id = WEAPON_NAME_IDX[weapon_name][0];
 | 
				
			||||
        console.log("show_trees(" + weapon_name + "): " + weapon_id);
 | 
				
			||||
        $("#weapon").val(weapon_name);
 | 
				
			||||
        $("#results").html("");
 | 
				
			||||
        $("#weapon_stats").html("");
 | 
				
			||||
        $.getJSON(DATA_PATH + "weapon/" + weapon_id + ".json",
 | 
				
			||||
                  function(data) {
 | 
				
			||||
                      set_sharpness_titles(data);
 | 
				
			||||
                      //set_horn_melodies_title(data);
 | 
				
			||||
                      if (data["parent_id"]) {
 | 
				
			||||
                          var parent_obj = WEAPON_ID_IDX[data["parent_id"]][0];
 | 
				
			||||
                          data["parent_name"] = parent_obj["name"];
 | 
				
			||||
                      } else {
 | 
				
			||||
                          data["parent_name"] = null;
 | 
				
			||||
                      }
 | 
				
			||||
                      data["sharpness_width"] = 0.4;
 | 
				
			||||
                      data["sharpness_plus2"] = null;
 | 
				
			||||
                      data["village_stars"] = 0
 | 
				
			||||
                      data["guild_stars"] = 0
 | 
				
			||||
                      var html = template_stats.render(data);
 | 
				
			||||
                      $("#weapon_stats").html(html);
 | 
				
			||||
                  });
 | 
				
			||||
 | 
				
			||||
        $.getJSON(DATA_PATH + "weapon/" + weapon_id + "_tree.json",
 | 
				
			||||
                  function(data) {
 | 
				
			||||
                      // first pass: collect all components and sort them
 | 
				
			||||
                      var all_dict = {};
 | 
				
			||||
                      for (i=0; i<data.length; i++) {
 | 
				
			||||
                          var components = Object.keys(data[i]["components"]);
 | 
				
			||||
                          for (j=0; j<components.length; j++) {
 | 
				
			||||
                              all_dict[components[j]] = 0;
 | 
				
			||||
                          }
 | 
				
			||||
                      }
 | 
				
			||||
                      var all_components = Object.keys(all_dict);
 | 
				
			||||
                      all_components.sort();
 | 
				
			||||
                      // second pass: generate the fieldset for each weapon
 | 
				
			||||
                      //  path. Note that the template uses all components
 | 
				
			||||
                      //  to order the components and make them line up
 | 
				
			||||
                      for (i=0; i<data.length; i++) {
 | 
				
			||||
                          delta = {};
 | 
				
			||||
                          path = data[i];
 | 
				
			||||
                          components = path["components"]
 | 
				
			||||
                          path_string = "";
 | 
				
			||||
                          for (j=0; j<path["path"].length; j++) {
 | 
				
			||||
                              if (j != 0) {
 | 
				
			||||
                                  path_string += " -> ";
 | 
				
			||||
                              }
 | 
				
			||||
                              path_string += path["path"][j]["name"];
 | 
				
			||||
                          }
 | 
				
			||||
                          path["path_string"] = path_string.replace(/"/g,
 | 
				
			||||
                                                                    '"');
 | 
				
			||||
                          path["all_components"] = all_components;
 | 
				
			||||
                          path["component_list"] = Object.keys(components);
 | 
				
			||||
                          if (i > 0) {
 | 
				
			||||
                              prev_comps = data[i-1]["components"];
 | 
				
			||||
                              $.each(components, function(name, quantity) {
 | 
				
			||||
                                   if (name in prev_comps) {
 | 
				
			||||
                                       delta[name] = components[name]
 | 
				
			||||
                                                     - prev_comps[name];
 | 
				
			||||
                                   }
 | 
				
			||||
                              });
 | 
				
			||||
                          }
 | 
				
			||||
                          path["delta"] = delta;
 | 
				
			||||
                          path["component_list"].sort();
 | 
				
			||||
                          path["trade_names"] = [];
 | 
				
			||||
                          for (j=0; j<all_components.length; j++) {
 | 
				
			||||
                              var name = all_components[j];
 | 
				
			||||
                              path["trade_names"][j] = "";
 | 
				
			||||
                          }
 | 
				
			||||
 
 | 
				
			||||
                          var html = template_path.render(path);
 | 
				
			||||
                          $("#results").append(html);
 | 
				
			||||
                      }
 | 
				
			||||
                  });
 | 
				
			||||
    }
 | 
				
			||||
  </script>
 | 
				
			||||
</head>
 | 
				
			||||
<body>
 | 
				
			||||
<div>
 | 
				
			||||
  <table>
 | 
				
			||||
  <tr>
 | 
				
			||||
    <td><label for="weapon_type">Type:</label></td>
 | 
				
			||||
    <td><select id="weapon_type">
 | 
				
			||||
        <option value="All">All</option>
 | 
				
			||||
        <option value="Great Sword">Great Sword</option>
 | 
				
			||||
        <option value="Long Sword">Long Sword</option>
 | 
				
			||||
        <option value="Sword and Shield">Sword and Shield</option>
 | 
				
			||||
        <option value="Dual Blades">Dual Blades</option>
 | 
				
			||||
        <option value="Hammer">Hammer</option>
 | 
				
			||||
        <option value="Hunting Horn">Hunting Horn</option>
 | 
				
			||||
        <option value="Lance">Lance</option>
 | 
				
			||||
        <option value="Gunlance">Gunlance</option>
 | 
				
			||||
        <option value="Switch Axe">Switch Axe</option>
 | 
				
			||||
        <option value="Charge Blade">Charge Blade</option>
 | 
				
			||||
        <option value="Insect Glaive">Insect Glaive</option>
 | 
				
			||||
        <option value="Light Bowgun">Light Bowgun</option>
 | 
				
			||||
        <option value="Heavy Bowgun">Heavy Bowgun</option>
 | 
				
			||||
        <option value="Bow">Bow</option>
 | 
				
			||||
    </select></td>
 | 
				
			||||
  </tr>
 | 
				
			||||
  <tr>
 | 
				
			||||
    <td><label for="weapon">Weapon:</label></td>
 | 
				
			||||
    <td><input id="weapon" name="weapon" size="20" />
 | 
				
			||||
    <button id="search">Ask Poogie</button></td>
 | 
				
			||||
  </tr>
 | 
				
			||||
  </table>
 | 
				
			||||
</div>
 | 
				
			||||
<div id="weapon_stats"></div>
 | 
				
			||||
<div id="results" class="flexbox"></div>
 | 
				
			||||
</body>
 | 
				
			||||
@ -0,0 +1,63 @@
 | 
				
			||||
<tr title="id: <%= id %>">
 | 
				
			||||
<td><% if (final == 1) { %>
 | 
				
			||||
      <strong>*</strong>
 | 
				
			||||
    <% } else { %>
 | 
				
			||||
       
 | 
				
			||||
    <% } %>
 | 
				
			||||
</td>
 | 
				
			||||
<td>
 | 
				
			||||
<a href="weaponplanner.html?weapon=<%= encodeURIComponent(name) %>"><%= name %></a>
 | 
				
			||||
</td>
 | 
				
			||||
<td><%= wtype_short %></td>
 | 
				
			||||
<td style="text-align:right"><%= attack %></td>
 | 
				
			||||
<td style="text-align:right"><% if (affinity) { %><%= affinity %>%<% } %></td>
 | 
				
			||||
<td>
 | 
				
			||||
<% if (element) { %>
 | 
				
			||||
  <img style="height:.8em" title="<%= element %>"
 | 
				
			||||
            src="/img/<%= element %>.png" /> <%= element_attack %>
 | 
				
			||||
            <%= ELEMENT_ABBR[element] %>
 | 
				
			||||
  <% if (element_2) { %>
 | 
				
			||||
    <img style="height:.8em" title="<%= element_2 %>"
 | 
				
			||||
            src="/img/<%= element_2 %>.png" /> <%= element_2_attack %>
 | 
				
			||||
            <%= ELEMENT_ABBR[element_2] %>
 | 
				
			||||
  <% } %>
 | 
				
			||||
<% } %>
 | 
				
			||||
</td>
 | 
				
			||||
<td id="sharpness_td"
 | 
				
			||||
    data-sharpness="<%= sharpness_all_title %>"
 | 
				
			||||
    data-id="<%= id %>">
 | 
				
			||||
<% if (sharpness) { %>
 | 
				
			||||
<div class="sharpness-bar" title="<%= sharpness_all_title %>">
 | 
				
			||||
<span style="width:<%= sharpness[0] * sharpness_width %>px" class="red"></span>
 | 
				
			||||
<span style="width:<%= sharpness[1] * sharpness_width %>px" class="orange"></span>
 | 
				
			||||
<span style="width:<%= sharpness[2] * sharpness_width %>px" class="yellow"></span>
 | 
				
			||||
<span style="width:<%= sharpness[3] * sharpness_width %>px" class="green"></span>
 | 
				
			||||
<span style="width:<%= sharpness[4] * sharpness_width %>px" class="blue"></span>
 | 
				
			||||
<span style="width:<%= sharpness[5] * sharpness_width %>px" class="white"></span>
 | 
				
			||||
<% if (sharpness.length > 6) { %>
 | 
				
			||||
<span style="width:<%= sharpness[6] * sharpness_width %>px" class="purple"></span>
 | 
				
			||||
<% } %>
 | 
				
			||||
</div>
 | 
				
			||||
<% } %>
 | 
				
			||||
<% if (sharpness_plus) { %>
 | 
				
			||||
<div class="sharpness-bar" title="<%= sharpness_all_title %>">
 | 
				
			||||
<span style="width:<%= sharpness_plus[0] * sharpness_width %>px" class="red"></span>
 | 
				
			||||
<span style="width:<%= sharpness_plus[1] * sharpness_width %>px" class="orange"></span>
 | 
				
			||||
<span style="width:<%= sharpness_plus[2] * sharpness_width %>px" class="yellow"></span>
 | 
				
			||||
<span style="width:<%= sharpness_plus[3] * sharpness_width %>px" class="green"></span>
 | 
				
			||||
<span style="width:<%= sharpness_plus[4] * sharpness_width %>px" class="blue"></span>
 | 
				
			||||
<span style="width:<%= sharpness_plus[5] * sharpness_width %>px" class="white"></span>
 | 
				
			||||
<% if (sharpness_plus.length > 6) { %>
 | 
				
			||||
<span style="width:<%= sharpness_plus[6] * sharpness_width %>px" class="purple"></span>
 | 
				
			||||
<% } %>
 | 
				
			||||
</div>
 | 
				
			||||
<% } %>
 | 
				
			||||
</td>
 | 
				
			||||
<td style="text-align:right"><%= phial %>
 | 
				
			||||
  <% if (phial_value) { %><%= phial_value %><% } %>
 | 
				
			||||
</td>
 | 
				
			||||
<td style="text-align:right"><%= shelling_type %>
 | 
				
			||||
  <% if (shelling_level) { %><%= shelling_level %><% } %>
 | 
				
			||||
</td>
 | 
				
			||||
<td style="text-align:right"><%= bug_level %></td>
 | 
				
			||||
<td><%= defense ? "+" + defense + " Def" : "" %></td>
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue