//import './App.css'; Old CSS import './reset.css'; // Generic reset import './style.css'; // The new new import React, {useState,useEffect,useRef,useReducer} from 'react'; import useGlobalKeyDown from 'react-global-key-down-hook' import Modal from 'react-modal' import Toggle from 'react-toggle' //Tooltip props: http://aaronshaf.github.io/react-toggle/ import {XSquare, XSquareFill, PlusCircle} from 'react-bootstrap-icons' import { HashRouter, Switch, Route } from "react-router-dom"; import { HashLink as Link } from 'react-router-hash-link'; import TestHeader from './TestHeader'; // Test Header! import TestPanel from './TestPanel'; // Dudley's Test Panel const axios = require('axios'); const parse = require('csv-parse/lib/sync') Function.prototype.toJSON = function() { return "Unstorable function" } /* Damage types const MELEE_DMG = 0 const RANGE_DMG = 1 const TECH_DMG = 2 Art properties const NORMAL = 0 const PHOTON_ART = 1 const WEAPON_ACTION = 2 const STEP_COUNTER = 3 const PARRY_COUNTER = 4 //NOT USED YET*/ const BACKENDURL=process.env.REACT_APP_GITPOD_WORKSPACE_URL||process.env.REACT_APP_BACKENDURL||'https://projectdivar.com:4504' function GetBackendURL(p) { return (BACKENDURL)+(p.TESTMODE?"/test":"") } function Col(p) { return
{p.children}
} function Box(p) { return <>

{p.title}

{p.children}
} function EditBox(p) { useEffect(()=>{ var timer1 = setTimeout(()=>{document.getElementById("editBox").focus()},100) return () => { clearTimeout(timer1); }; }) return { if (e.key==="Enter") {p.setEdit(false)} else if (e.key==="Escape") {p.setEdit(false)} }} maxLength={p.maxlength?p.maxlength:20} onBlur={()=>{p.setEdit(false)}} value={p.value} onChange={(f)=>{f.currentTarget.value.length>0?p.setName(f.currentTarget.value):p.setName(p.originalName)}}> } function EditableBox(p) { const [edit,setEdit] = useState(false) useEffect(()=>{ if (p.callback) { p.callback() } },[edit,p]) return <>
{setEdit(true)}}> {edit? :<>{p.data}}
} const CLASSES = { HUNTER:{ name:"Hunter", icon:process.env.PUBLIC_URL+"/icons/UINGSClassHu.png" }, FIGHTER:{ name:"Fighter", icon:process.env.PUBLIC_URL+"/icons/UINGSClassFi.png" }, RANGER:{ name:"Ranger", icon:process.env.PUBLIC_URL+"/icons/UINGSClassRa.png" }, GUNNER:{ name:"Gunner", icon:process.env.PUBLIC_URL+"/icons/UINGSClassGu.png" }, FORCE:{ name:"Force", icon:process.env.PUBLIC_URL+"/icons/UINGSClassFo.png" }, TECHTER:{ name:"Techter", icon:process.env.PUBLIC_URL+"/icons/UINGSClassTe.png" } } const EFFECTS = { "Food Boost Effect":{ perks:[ "[Meat] Potency +10.0%", "[Crisp] Potency to Weak Point +5.0%" ], icon:process.env.PUBLIC_URL+"/icons/TQ8EBW2.png" }, "Shifta / Deband":{ perks:[ "Potency +5.0%", "Damage Resistance +10.0%" ], icon:process.env.PUBLIC_URL+"/icons/VIYYNIm.png" }, "Region Mag Boost":{ perks:[ "Potency +5.0%", ], icon:process.env.PUBLIC_URL+"/icons/N6M74Qr.png" }, } const EQUIPMENT = { "Ophistia Shooter":{ icon:process.env.PUBLIC_URL+"/icons/uc1iBck.png" }, "Klauzdyne":{ icon:process.env.PUBLIC_URL+"/icons/uldt9lR.png" }, "Klauznum":{ icon:process.env.PUBLIC_URL+"/icons/F0t58xP.png" }, "Klauzment":{ icon:process.env.PUBLIC_URL+"/icons/20M6Z7t.png" } } const ABILITIES = { "Wellspring Unit Lv.3":{ icon:process.env.PUBLIC_URL+"/icons/NGSUIItemPotentialAbility.png" }, "Fixa Fatale Lv.5":{ icon:process.env.PUBLIC_URL+"/icons/UINGSItemPresetAbility.png" } } const ABILITY_DEFAULT_ICON = process.env.PUBLIC_URL+"/icons/UINGSItemSpecialAbility.png" /** * Hook that alerts clicks outside of the passed ref */ function useOutsideAlerter(ref,setEdit) { useEffect(() => { /** * Alert if clicked on outside of element */ function handleClickOutside(event) { if (ref.current && !ref.current.contains(event.target)) { setEdit(false) } } // Bind the event listener document.addEventListener("mousedown", handleClickOutside); return () => { // Unbind the event listener on clean up document.removeEventListener("mousedown", handleClickOutside); }; }, [ref,setEdit]); } function Class(p) { const class_obj = CLASSES[p.name] return <>{class_obj.name} } function ClassSelector(p){ const wrapperRef = useRef(null); useOutsideAlerter(wrapperRef,p.setEdit); return
Class Selector
{Object.keys(CLASSES).map((cl,i)=>{ return })}
} function EditableClass(p){ const [edit,setEdit] = useState(false) return <>{setEdit(!edit)}}> {edit&&} } function Table(p) { return

{p.children}

} function MainBox(p) { return }>Lv.20}>Lv.15
} function StatsBox(p) { return +{p.weaponUp1*100}%}> +{p.weaponUp2*100}% +{p.weaponUp3*100}%}>
} function EffectListing(p) { return
  • {p.name}
  • } function PageControlButton(p) { return
  • {p.setCurrentPage(p.page)}} className={(p.currentPage===p.page)?"selected":""}>{p.pageName?p.pageName:p.page}
  • } function PageControl(p) { var pages = [] for (var i=0;i) } return } function EffectsBox(p) { const [currentPage,setCurrentPage]=useState(1) return

    Effect Name

    { currentPage===1?
      {p.effectList.map((ef,i)=>{ return })}
    : <> }
    } function EquipBox(p) { return

    Weapon



    {p.weapon}+{p.weaponEnhancementLv}

    Slot 1



    {p.armorSlot1}+{p.armorSlot1EnhancementLv}

    Slot 2



    {p.armorSlot2}+{p.armorSlot2EnhancementLv}

    Slot 3



    {p.armorSlot3}+{p.armorSlot3EnhancementLv}
    } function EquippedWeaponBox(p) { const [currentPage,setCurrentPage] = useState(1) const [selectedEquip,setSelectedEquip] = useState(p.weapon) const [selectedEquipEnhancementLv,setSelectedEquipEnhancementLv] = useState(p.weaponEnhancementLv) const [selectedEquipAbilities,setSelectedEquipAbilities] = useState(p.weaponAbilityList) useEffect(()=>{ switch (currentPage) { case 2: setSelectedEquip(p.armorSlot1) setSelectedEquipEnhancementLv(p.armorSlot1EnhancementLv) setSelectedEquipAbilities(p.armorSlot1AbilityList) break; case 3: setSelectedEquip(p.armorSlot2) setSelectedEquipEnhancementLv(p.armorSlot2EnhancementLv) setSelectedEquipAbilities(p.armorSlot2AbilityList) break; case 4: setSelectedEquip(p.armorSlot3) setSelectedEquipEnhancementLv(p.armorSlot3EnhancementLv) setSelectedEquipAbilities(p.armorSlot3AbilityList) break; default:{ setSelectedEquip(p.weapon) setSelectedEquipEnhancementLv(p.weaponEnhancementLv) setSelectedEquipAbilities(p.weaponAbilityList) } } },[currentPage,p.armorSlot1,p.armorSlot1EnhancementLv,p.armorSlot1AbilityList,p.armorSlot2,p.armorSlot2EnhancementLv,p.armorSlot2AbilityList,p.armorSlot3,p.armorSlot3EnhancementLv,p.armorSlot3AbilityList,p.weapon,p.weaponEnhancementLv,p.weaponAbilityList]) return

    {selectedEquip}+{selectedEquipEnhancementLv}

    Ability Details

      { selectedEquipAbilities?selectedEquipAbilities.map((ability,i)=>{ return
    • {ability}
    • }):<> }

    Properties

    • Enhancement Lv. +{selectedEquipEnhancementLv}
    • Multi-Weapon -
    • Element -
    } function DamageBox(p) { const [currentPage,setCurrentPage] = useState(1) return

    { currentPage===1&& {p.criticalHitRate*100}%{p.criticalMultiplier*100}%{p.midRange}{p.critical}{p.effective}
    }
    } function ListRow(p) { return {p.title} {p.content} {p.children} } function PopupWindow(p) { return {p.setModalOpen(false)}} shouldFocusAfterRender={true} shouldCloseOnOverlayClick={true} shouldCloseOnEsc={true}>

    {p.title}{p.showCloseButton&&{p.setModalOpen(false)}} className="modalCloseButton"/>}

    {p.children}
    } function InputBox(p) { const [value,setValue] = useState(p.value) const [failed,setFailed] = useState(false) const [sending,setSending] = useState(false) function changeFunc(f){setValue(f.currentTarget.value) if (p.callback4) { p.callback4(f.currentTarget.value) }} function blurFunc(f){ if (p.callback) { setSending(true) setFailed(false) p.callback(f.currentTarget.value) .then(()=>{setFailed(false)}) .catch(()=>{setFailed(true)}) .then(()=>{setSending(false)})} else if (p.callback3) { p.callback3(f.currentTarget.value) }} function keydownFunc(f){ if (p.callback2) { p.callback2(f,value) } } return p.data?:{keydownFunc(f)}} onChange={(f)=>{changeFunc(f)}} onBlur={(f)=>{blurFunc(f)}}/> } function TableEditor(p) { const initialVals={} function updateVals(state,update) { if (update==='Clear') { return initialVals } state[update.field]=update.value return state } const [fields,setFields] = useState([]) const [data,setData] = useState([]) const [update,setUpdate] = useState(false) const [submitVals,setSubmitVal] = useReducer(updateVals,initialVals) const [loading,setLoading] = useState(false) const [dependencies,setDependencies] = useState([]) const [importAllowed,setImportAllowed] = useState(false) const [fileData,setFileData] = useState(undefined) const [lockSubmission,setLockSubmission] = useState(false) function SubmitBoxes() { if (!lockSubmission) { setLockSubmission(true) axios.post(p.BACKENDURL+p.path,submitVals) .then(()=>{ setSubmitVal("Clear") setUpdate(true) }) .catch((err)=>{ alert(JSON.stringify(err.response.data)) }) .then(()=>{ setLockSubmission(false) }) } } useGlobalKeyDown(()=>{ SubmitBoxes() },['Enter']) useEffect(()=>{ setUpdate(true) },[p.path]) useEffect(()=>{ var promises=[] parse(fileData,{columns:true,skip_empty_lines:true}).forEach((entry)=>{ promises.push(axios.post(p.BACKENDURL+p.path,entry)) }) Promise.allSettled(promises) .then(()=>{ setUpdate(true) }) },[fileData,p.path,p.BACKENDURL]) useEffect(()=>{ for (var col of fields) { if (col.name==="name") { setImportAllowed(true) break; } } },[fields]) useEffect(()=>{ if (update) { setLoading(true) var dependency_map = {} axios.get(p.BACKENDURL+p.path) .then((data)=>{ var cols = data.data.fields var rows = data.data.rows setFields(cols.filter((col,i)=>col.name!=="id"&&!(i===0&&col.name==="name"))) var promise_list = [] cols.filter((col)=>col.name!=="id"&&col.name.includes("_id")).forEach((col)=>{ promise_list.push(axios.get(p.BACKENDURL+"/"+col.name.replace("_id","")) .then((data)=>{ dependency_map[col.name]=data.data.rows.sort((a,b)=>b.id-a.id) })) }) setData(rows) return Promise.allSettled(promise_list) }) .then(()=>{ setDependencies(dependency_map) setLoading(false) }) setUpdate(false) } },[update,p.path,p.BACKENDURL]) return <> {!loading?
    {importAllowed&&} {fields.map((field,i)=>)} {{fields.map((col,i)=>)}{SubmitBoxes()}} className="submitbutton"/>} {data.map((dat)=>{fields.map((col,i)=>)})}
    { const reader = new FileReader() reader.onload=(ev)=>{ setFileData(ev.target.result) } reader.readAsText(f.target.files[0]) }} style={{opacity:0}} id="uploads" type="file" accept=".txt,.csv"/>
    {field.name}
    {{setSubmitVal({field:col.name,value:f});}}/>}
    {axios.delete(p.BACKENDURL+p.path,{data:{id:dat.id}}).then(()=>{setUpdate(true)}).catch((err)=>{alert(err.response.data)})}}/> { return axios.patch(p.BACKENDURL+p.path,{ [col.name]:value, id:dat.id }) }} value={String(dat[col.name])}/>
    :} } function DatabaseEditor(p) { const [loading,setLoading] = useState(false) return <> {!loading?<>





    : } } function AdminPanel(p) { return
    Class
    Class Data
    Class-Weapon Compatibility
    Class Skills
    Class Skill Data

    Weapons
    Weapon Existence Data
    Weapon Types
    Class-Weapon Compatibility
    Photon Arts

    Armor
    Potentials
    Potential Data

    Builds

    Skills
    Skill Types
    Skill Data
    Photon Arts
    Class Skills
    Class Skill Data

    Augments
    Augment Types

    Enemy Data

    Food
    Food Multipliers

    Roles
    Users

    Database Audit
    Database Manager
    } function EditStatBox(p) { const [value,setValue] = useState(p.value) useEffect(()=>{ setValue(p.value) },[p.value]) return <>{setValue(f.currentTarget.value);p.callback(f.currentTarget.value)}}/> ({value})
    } function DamageCalculator(p) { const [augmentData,setAugmentData] = useState({}) //const [update,setUpdate] = useState(false) useEffect(()=>{ axios.get(p.BACKENDURL+"/augment") .then((data)=>{ var augmentData = {} data.data.rows.forEach((entry)=>{augmentData[entry.name]=entry}) setAugmentData(augmentData) }) },[p.BACKENDURL]) const character = { weapon:{ augments:["1","2"] }, armor1:{ augments:["2"] }, armor2:{ augments:[] }, armor3:{ augments:[] } } useEffect(()=>{ if (Object.keys(augmentData).length>0) { var searchFields = [{field:"variance",variable:0},{field:"mel_dmg",variable:0}] for (var equip of [character.weapon,character.armor1,character.armor2,character.armor3]) { for (var field of searchFields) { for (var i=0;i{ setWeaponTotalAtk(Number(weaponBaseAtk)+Number(weaponEnhanceLvl)) },[weaponBaseAtk,weaponEnhanceLvl]) const [dmgVariance,setDmgVariance] = useState(1) const [weaponDmgVariance,setWeaponDmgVariance] = useState(1) const [augDmgVariance,setAugDmgVariance] = useState(1) useEffect(()=>{ setDmgVariance(Number(weaponDmgVariance)+Number(augDmgVariance)) },[weaponDmgVariance,augDmgVariance]) const [baseAtk,setBaseAtk] = useState(100) const [enemyDef,setEnemyDef] = useState(5) const [multipliers,setMultipliers] = useState(1) useEffect(()=>{ setRawDmg(((Number(weaponTotalAtk)*Number(dmgVariance))+Number(baseAtk)-Number(enemyDef))*Number(multipliers)/5) },[weaponTotalAtk,dmgVariance,baseAtk,enemyDef,multipliers]) const [atkmult,setAtkMult] = useState(1); const [partmult,setPartMult] = useState(1); const [elementalWeaknessMult,setElementalWeaknessMult] = useState(1.2) const [mainClassWeaponBoost,setMainClassWeaponBoost] = useState(1.1) const [classSkillMult,setClassSkillMult] = useState(1) const [equipMult,setEquipMult] = useState(1) const [augmentEquipMult,setAugmentEquipMult] = useState(1) const [potencyFloorEquipMult,setPotencyFloorEquipMult] = useState(1) const [elementalWeaponEquipMult,setElementalWeaponEquipMult] = useState(1.1) const [critMult,setCritMult] = useState(1.2) const [appropriateDistance,setAppropriateDistance] = useState(1) const [foodBoost,setFoodBoost] = useState(1) const [fieldEffects,setFieldEffects] = useState(1.05) const [statusAilments,setStatusAilments] = useState(1) const [enemyCorrectionMult,setEnemyCorrectionMult] = useState(1) const [highLevelEnemy,setHighLevelEnemy] = useState(1) useEffect(()=>{ setMultipliers(Number(atkmult)*Number(partmult)*Number(elementalWeaknessMult)*Number(mainClassWeaponBoost)*Number(classSkillMult)*Number(equipMult)*Number(augmentEquipMult)*Number(potencyFloorEquipMult)*Number(elementalWeaponEquipMult)*Number(critMult)*Number(appropriateDistance)*Number(foodBoost)*Number(fieldEffects)*Number(statusAilments)*Number(enemyCorrectionMult)*Number(highLevelEnemy)) },[atkmult,partmult,elementalWeaknessMult,mainClassWeaponBoost,classSkillMult,equipMult,augmentEquipMult,potencyFloorEquipMult,elementalWeaponEquipMult,critMult,appropriateDistance,foodBoost,fieldEffects,statusAilments,enemyCorrectionMult,highLevelEnemy]) return <>
    Weapon Total Atk:{setWeaponTotalAtk(val)}}/>
    • ●Weapon Base Atk:{setWeaponBaseAtk(val)}}/>
    • ●Weapon Enhance Lvl:{setWeaponEnhanceLvl(val)}}/>



    Damage Variance:{setDmgVariance(val)}}/>
    • ●Weapon Damage Variance:{setWeaponDmgVariance(val)}}/>
    • ●Augment Damage Variance:{setAugDmgVariance(val)}}/>



    Base Attack:{setBaseAtk(val)}}/> Enemy Defense:{setEnemyDef(val)}}/> Multipliers:{setMultipliers(val)}}/>
    • ●Atk Mult:{setAtkMult(val)}}/>
    • ●Part Mult:{setPartMult(val)}}/>
    • ●Elemental Weakness Mult:{setElementalWeaknessMult(val)}}/>
    • ●Main Class Weapon Boost:{setMainClassWeaponBoost(val)}}/>
    • ●Class Skill Mult:{setClassSkillMult(val)}}/>
    • ●Equip Mult:{setEquipMult(val)}}/>
      • ●Augment Equip Mult:{setAugmentEquipMult(val)}}/>
      • ●Potency Floor Equip Mult:{setPotencyFloorEquipMult(val)}}/>
      • ●Elemental Weapon Equip Mult:{setElementalWeaponEquipMult(val)}}/>
    • ●Crit Mult:{setCritMult(val)}}/>
    • ●Appropriate Distance:{setAppropriateDistance(val)}}/>
    • ●Food Boost:{setFoodBoost(val)}}/>
    • ●Field Effects:{setFieldEffects(val)}}/>
    • ●Status Ailments:{setStatusAilments(val)}}/>
    • ●Enemy Correction Multiplier:{setEnemyCorrectionMult(val)}}/>
    • ●High Level Enemy:{setHighLevelEnemy(val)}}/>



    Raw Dmg:{rawDmg}
    } function App() { const [author,setAuthor] = useState("Dudley") const [buildName,setBuildName] = useState("Fatimah") const [className,setClassName] = useState("Ranger") const [secondaryClassName,setSecondaryClassName] = useState("Force") const [bp,setBP] = useState(1330) const [hp,setHP] = useState(388) const [pp,setPP] = useState(154) const [weaponTotalAtk,setweaponTotalAtk] = useState(282) const [baseAtk,setbaseAtk] = useState(650) const [statDisplayAtk,setstatDisplayAtk] = useState(282) useEffect(()=>{ setstatDisplayAtk(Number(weaponTotalAtk)+Number(baseAtk)) },[weaponTotalAtk,baseAtk]) const [def,setDef] = useState(932) const [weaponUp1,setWeaponUp1] = useState(0.317) const [weaponUp2,setWeaponUp2] = useState(0.241) const [weaponUp3,setWeaponUp3] = useState(0.241) const [damageResist,setDamageResist] = useState(0.18) const [effectList,setEffectList] = useState([ "Food Boost Effect", "Shifta / Deband", "Region Mag Boost" ]) const [weapon,setWeapon] = useState("Ophistia Shooter") const [armorSlot1,setArmorSlot1] = useState("Klauzdyne") const [armorSlot2,setArmorSlot2] = useState("Klauznum") const [armorSlot3,setArmorSlot3] = useState("Klauzment") const [weaponEnhancementLv,setWeaponEnhancementLv] = useState(35) const [armorSlot1EnhancementLv,setArmorSlot1EnhancementLv] = useState(10) const [armorSlot2EnhancementLv,setArmorSlot2EnhancementLv] = useState(10) const [armorSlot3EnhancementLv,setArmorSlot3EnhancementLv] = useState(10) const [weaponAbilityList,setWeaponAbilityList] = useState([ "Wellspring Unit Lv.3", "Fixa Fatale Lv.5", "Legaro S Attack II", "Legaro S Efficiet", "Legaro S Efficiet", "Legaro Souls 2", "Legaro Reverij", "Legaro Factalz", "Legaro Crakus", "Legaro Attack Vaz III", ]) const [armor1AbilityList,setArmor1AbilityList] = useState([]) const [armor2AbilityList,setArmor2AbilityList] = useState([]) const [armor3AbilityList,setArmor3AbilityList] = useState([]) const [criticalHitRate,setCriticalHitRate] = useState(0.05) const [criticalMultiplier,setCriticalMultiplier] = useState(1.2) const [midRange,setMidRange] = useState(126) const [critical,setCritical] = useState(152) const [effective,setEffective] = useState(127) const [modalOpen,setModalOpen] = useState(true) const [TESTMODE,setTESTMODE] = useState(false) const [DATA,setDATA] = useState({GetData:()=>{}}) function GetData(table,row,col){ return DATA!==undefined?DATA[table]!==undefined?DATA[table][row]!==undefined?DATA[table][row][col]!==undefined?DATA[table][row][col]:DATA[table][row]:DATA[table]:DATA:"no data" } useEffect(()=>{ axios.get(GetBackendURL({TESTMODE:TESTMODE})+"/data") .then((data)=>{ setDATA(data.data) }) },[TESTMODE]) return ( <>
    Modal content goes here.{BACKENDURL}

    {setTESTMODE(t.target.checked)}}/>Test Mode: {JSON.stringify(TESTMODE)}

    {"Fighter Icon URL: "+GetData("class","Fighter","icon")}

    Gunner Level Stats:{ [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] .map((numb)=>{ var data=GetData("class_level_data","Gunner Lv."+numb); return <>
    {"Lv."+data.level+": "+data.hp+","+data.atk+","+data.def} })}
    ); } export default App;