Skip to content

Commit 0d81c38

Browse files
committed
Initial commit
0 parents  commit 0d81c38

File tree

18 files changed

+2812
-0
lines changed

18 files changed

+2812
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Tony Dong
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# DaUmega Tools
2+
3+
This repository contains a growing collection of small, privacy-friendly web apps and utilities I’ve built.
4+
5+
All tools are:
6+
- **Free and open source**
7+
- **No accounts, no ads, no tracking**
8+
- **No data collection**
9+
- **Desktop and mobile friendly**
10+
11+
🌐 Live site: https://daumega.github.io/
12+
13+
---
14+
15+
## Tools
16+
17+
This repository hosts a variety of independent tools, including (but not limited to):
18+
19+
- Calculators and planners
20+
- Data visualization utilities
21+
- Privacy-focused personal tools
22+
- Peer-to-peer web apps
23+
- Game-related utilities
24+
- Frontend-only demos and prototypes
25+
26+
New tools may be added, improved, or retired over time.
27+
28+
For the most up-to-date list, browse the repository folders or visit the live site.
29+
30+
---
31+
32+
## Philosophy
33+
34+
These tools are intentionally:
35+
- Minimal
36+
- Fast
37+
- Easy to understand
38+
- Easy to self-host or fork
39+
40+
Most projects favor simplicity over features and avoid unnecessary dependencies.
41+
42+
---
43+
44+
## Contributing
45+
46+
Contributions, suggestions, and bug reports are welcome.
47+
48+
- Open an issue for feedback or ideas
49+
- Submit a pull request for fixes or improvements
50+
51+
---
52+
53+
## License
54+
55+
MIT License

WFCalculator/index.html

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>⚔️ Wing Fighter PvP Calculator</title>
7+
<link rel="stylesheet" href="styles.css" />
8+
</head>
9+
<body>
10+
<h1>⚔️ Wing Fighter PvP Calculator</h1>
11+
12+
<div class="notice">
13+
⚠️ This calculator provides estimates based on simplified formulas. Use it for general guidance only.
14+
</div>
15+
16+
<div class="form-container">
17+
<div class="grid-headings">
18+
<div class="player-title">🛩️ Player</div>
19+
<div class="enemy-title">👾 Enemy</div>
20+
</div>
21+
22+
<div class="form-grid">
23+
<!-- Weapon Type -->
24+
<div class="stat-row">
25+
<div class="stat-title">Weapon Type</div>
26+
<select class="player-input" id="playerWeaponType">
27+
<option value="physical">Physical</option>
28+
<option value="energy">Energy</option>
29+
</select>
30+
<select class="enemy-input" id="enemyWeaponType">
31+
<option value="physical">Physical</option>
32+
<option value="energy">Energy</option>
33+
</select>
34+
</div>
35+
36+
<!-- Power -->
37+
<div class="stat-row">
38+
<div class="stat-title">Power (P)</div>
39+
<input class="player-input" type="number" id="playerPower" placeholder="e.g. 1000000" />
40+
<input class="enemy-input" type="number" id="enemyPower" placeholder="e.g. 1000000" />
41+
</div>
42+
43+
<!-- Physical Defense Break -->
44+
<div class="stat-row">
45+
<div class="stat-title">Physical Defense Break (PDB)</div>
46+
<input class="player-input" type="number" id="playerPhysBreak" placeholder="e.g. 1000" />
47+
<input class="enemy-input" type="number" id="enemyPhysBreak" placeholder="e.g. 1000" />
48+
</div>
49+
50+
<!-- Physical Defense -->
51+
<div class="stat-row">
52+
<div class="stat-title">Physical Defense (PD)</div>
53+
<input class="player-input" type="number" id="playerPhysDef" placeholder="e.g. 1000" />
54+
<input class="enemy-input" type="number" id="enemyPhysDef" placeholder="e.g. 1000" />
55+
</div>
56+
57+
<!-- Energy Defense Break -->
58+
<div class="stat-row">
59+
<div class="stat-title">Energy Defense Break (EDB)</div>
60+
<input class="player-input" type="number" id="playerEnergyBreak" placeholder="e.g. 1000" />
61+
<input class="enemy-input" type="number" id="enemyEnergyBreak" placeholder="e.g. 1000" />
62+
</div>
63+
64+
<!-- Energy Defense -->
65+
<div class="stat-row">
66+
<div class="stat-title">Energy Defense (ED)</div>
67+
<input class="player-input" type="number" id="playerEnergyDef" placeholder="e.g. 1000" />
68+
<input class="enemy-input" type="number" id="enemyEnergyDef" placeholder="e.g. 1000" />
69+
</div>
70+
71+
<!-- Extra Damage vs Aerial -->
72+
<div class="stat-row">
73+
<div class="stat-title">Extra Damage vs Aerial (%)</div>
74+
<input class="player-input" type="number" id="playerExtraAerial" placeholder="e.g. 50" />
75+
<input class="enemy-input" type="number" id="enemyExtraAerial" placeholder="e.g. 50" />
76+
</div>
77+
78+
<!-- Damage Reduction vs Aerial -->
79+
<div class="stat-row">
80+
<div class="stat-title">Damage Reduction vs Aerial (%)</div>
81+
<input class="player-input" type="number" id="playerReduceAerial" placeholder="e.g. 50" />
82+
<input class="enemy-input" type="number" id="enemyReduceAerial" placeholder="e.g. 50" />
83+
</div>
84+
85+
<!-- Extra Damage vs Players -->
86+
<div class="stat-row">
87+
<div class="stat-title">Extra Damage vs Players (%)</div>
88+
<input class="player-input" type="number" id="playerExtraPlayer" placeholder="e.g. 30" />
89+
<input class="enemy-input" type="number" id="enemyExtraPlayer" placeholder="e.g. 30" />
90+
</div>
91+
92+
<!-- Damage Reduction vs Players -->
93+
<div class="stat-row">
94+
<div class="stat-title">Damage Reduction vs Players (%)</div>
95+
<input class="player-input" type="number" id="playerReducePlayer" placeholder="e.g. 30" />
96+
<input class="enemy-input" type="number" id="enemyReducePlayer" placeholder="e.g. 30" />
97+
</div>
98+
</div>
99+
100+
<!-- Optional Stats Toggle -->
101+
<div class="optional-section">
102+
<button id="toggleOptionalBtn" type="button">⚙️ Show Optional Stats</button>
103+
104+
<div id="optionalFields" class="optional-fields" style="display: none;">
105+
<div class="stat-row">
106+
<div class="stat-title">Maingun Attack</div>
107+
<input class="player-input" type="number" id="playerMGAttack" placeholder="e.g. 100000" />
108+
<input class="enemy-input" type="number" id="enemyMGAttack" placeholder="e.g. 100000" />
109+
</div>
110+
111+
<div class="stat-row">
112+
<div class="stat-title">Winggun Attack</div>
113+
<input class="player-input" type="number" id="playerWGAttack" placeholder="e.g. 100000" />
114+
<input class="enemy-input" type="number" id="enemyWGAttack" placeholder="e.g. 100000" />
115+
</div>
116+
117+
<div class="stat-row">
118+
<div class="stat-title">Missile Attack</div>
119+
<input class="player-input" type="number" id="playerMSLAttack" placeholder="e.g. 100000" />
120+
<input class="enemy-input" type="number" id="enemyMSLAttack" placeholder="e.g. 100000" />
121+
</div>
122+
123+
<p class="note"><small>These are optional, more may be added in future versions.</small></p>
124+
</div>
125+
</div>
126+
127+
<button id="calculateBtn">Calculate</button>
128+
129+
<p class="note">
130+
<small>This calculator uses estimated, simplified formulas, and does not factor in drones, if your opponent has high Drone PVP stats like Cheating Death, adjust your estimates accordingly.</small>
131+
</p>
132+
</div>
133+
134+
<div id="results" class="results-container" style="display:none;">
135+
<h3>📊 Results</h3>
136+
<ul>
137+
<li><strong>Player Effective Power:</strong> <span id="playerEffectivePower">0</span></li>
138+
<li><strong>Enemy Effective Power:</strong> <span id="enemyEffectivePower">0</span></li>
139+
<li><strong>Estimated Win Probability (player):</strong> <span id="winChance">0%</span></li>
140+
</ul>
141+
</div>
142+
143+
<button id="goBackBtn">← Go Back</button>
144+
145+
<script src="script.js"></script>
146+
</body>
147+
</html>

WFCalculator/script.js

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
const toggleBtn = document.getElementById("toggleOptionalBtn");
2+
const optionalFields = document.getElementById("optionalFields");
3+
4+
document.getElementById("calculateBtn").addEventListener("click", () => {
5+
// --- Read helper to parse numeric inputs safely ---
6+
function num(id, def = 0) {
7+
const v = parseFloat(document.getElementById(id)?.value);
8+
return (isNaN(v) ? def : v);
9+
}
10+
11+
// --- Gather player inputs ---
12+
const player = {
13+
weaponType: document.getElementById("playerWeaponType").value,
14+
power: num("playerPower", NaN),
15+
physBreak: num("playerPhysBreak", 0),
16+
physDef: num("playerPhysDef", 0),
17+
energyBreak: num("playerEnergyBreak", 0),
18+
energyDef: num("playerEnergyDef", 0),
19+
extraAerial: num("playerExtraAerial", 0),
20+
reduceAerial: num("playerReduceAerial", 0),
21+
extraPlayer: num("playerExtraPlayer", 0),
22+
reducePlayer: num("playerReducePlayer", 0),
23+
24+
// Optional weapon-specific attacks
25+
MGAttack: num("playerMGAttack", 0),
26+
WGAttack: num("playerWGAttack", 0),
27+
MSLAttack: num("playerMSLAttack", 0),
28+
};
29+
30+
// --- Gather enemy inputs ---
31+
const enemy = {
32+
weaponType: document.getElementById("enemyWeaponType").value,
33+
power: num("enemyPower", NaN),
34+
physBreak: num("enemyPhysBreak", 0),
35+
physDef: num("enemyPhysDef", 0),
36+
energyBreak: num("enemyEnergyBreak", 0),
37+
energyDef: num("enemyEnergyDef", 0),
38+
extraAerial: num("enemyExtraAerial", 0),
39+
reduceAerial: num("enemyReduceAerial", 0),
40+
extraPlayer: num("enemyExtraPlayer", 0),
41+
reducePlayer: num("enemyReducePlayer", 0),
42+
43+
// Optional weapon-specific attacks
44+
MGAttack: num("enemyMGAttack", 0),
45+
WGAttack: num("enemyWGAttack", 0),
46+
MSLAttack: num("enemyMSLAttack", 0),
47+
};
48+
49+
// Basic validation
50+
if (!isFinite(player.power) || player.power <= 0 || !isFinite(enemy.power) || enemy.power <= 0) {
51+
alert("Please enter valid positive Power values for both Player and Enemy.");
52+
return;
53+
}
54+
55+
// Calculation function
56+
function effectivePower(attacker, defender) {
57+
const breakStat = (attacker.weaponType === "physical") ? attacker.physBreak : attacker.energyBreak;
58+
const defenseStat = (attacker.weaponType === "physical") ? defender.physDef : defender.energyDef;
59+
60+
const rawFactor = 1 + ((breakStat - defenseStat) * 0.001);
61+
const clampedFactor = Math.max(0.5, Math.min(1.5, rawFactor));
62+
63+
const aerialNet = attacker.extraAerial - defender.reduceAerial;
64+
const playerNet = attacker.extraPlayer - defender.reducePlayer;
65+
66+
const aerialFactor = 1 + (aerialNet / 100);
67+
const playerFactor = 1 + (playerNet / 100);
68+
69+
const safeAerial = Math.max(0, aerialFactor);
70+
const safePlayer = Math.max(0, playerFactor);
71+
72+
const totalMultiplier = safeAerial * safePlayer;
73+
return { clampedFactor, totalMultiplier };
74+
}
75+
76+
// --- Calculate effective multipliers ---
77+
const playerFactors = effectivePower(player, enemy);
78+
const enemyFactors = effectivePower(enemy, player);
79+
80+
// --- Apply same scaling to Power and the optional attack stats ---
81+
function scaleStats(entity, factors) {
82+
return {
83+
effectivePower: entity.power * factors.clampedFactor * factors.totalMultiplier,
84+
effectiveMG: entity.MGAttack * factors.clampedFactor * factors.totalMultiplier,
85+
effectiveWG: entity.WGAttack * factors.clampedFactor * factors.totalMultiplier,
86+
effectiveMSL: entity.MSLAttack * factors.clampedFactor * factors.totalMultiplier,
87+
};
88+
}
89+
90+
const playerScaled = scaleStats(player, playerFactors);
91+
const enemyScaled = scaleStats(enemy, enemyFactors);
92+
93+
// --- Win chance (same as before) ---
94+
let winChance;
95+
if (enemyScaled.effectivePower <= 0 && playerScaled.effectivePower <= 0) {
96+
winChance = 50;
97+
} else if (enemyScaled.effectivePower <= 0) {
98+
winChance = 100;
99+
} else {
100+
const ratio = playerScaled.effectivePower / enemyScaled.effectivePower;
101+
const steepness = 10;
102+
winChance = Math.round(100 / (1 + Math.exp(-steepness * (ratio - 1))));
103+
winChance = Math.max(0, Math.min(100, winChance));
104+
}
105+
106+
// --- Output results ---
107+
document.getElementById("playerEffectivePower").textContent = playerScaled.effectivePower.toFixed(2);
108+
document.getElementById("enemyEffectivePower").textContent = enemyScaled.effectivePower.toFixed(2);
109+
110+
// Create or update comparison lines for MG/WG/MSL if applicable
111+
function setStatLine(id, label, playerVal, enemyVal) {
112+
if (playerVal > 0 || enemyVal > 0) {
113+
let elem = document.getElementById(id);
114+
if (!elem) {
115+
const ul = document.querySelector("#results ul");
116+
elem = document.createElement("li");
117+
elem.id = id;
118+
ul.appendChild(elem);
119+
}
120+
elem.innerHTML = `<strong>${label}:</strong> Player ${playerVal.toFixed(2)} vs Enemy ${enemyVal.toFixed(2)}`;
121+
} else {
122+
// Remove the line if it exists but both values are 0
123+
const elem = document.getElementById(id);
124+
if (elem) elem.remove();
125+
}
126+
}
127+
128+
setStatLine("mgCompare", "Main Gun Effective Attack", playerScaled.effectiveMG, enemyScaled.effectiveMG);
129+
setStatLine("wgCompare", "Wing Gun Effective Attack", playerScaled.effectiveWG, enemyScaled.effectiveWG);
130+
setStatLine("mslCompare", "Missile Effective Attack", playerScaled.effectiveMSL, enemyScaled.effectiveMSL);
131+
132+
document.getElementById("winChance").textContent = `${winChance}%`;
133+
document.getElementById("results").style.display = "block";
134+
});
135+
136+
document.getElementById("goBackBtn").addEventListener("click", () => {
137+
window.location.href = "../index.html";
138+
});
139+
140+
// Toggle Optional Stats section
141+
toggleBtn.addEventListener("click", () => {
142+
const isVisible = optionalFields.style.display === "block";
143+
if (isVisible) {
144+
optionalFields.style.display = "none";
145+
toggleBtn.textContent = "⚙️ Show Optional Stats";
146+
} else {
147+
optionalFields.style.display = "block";
148+
toggleBtn.textContent = "⚙️ Hide Optional Stats";
149+
}
150+
});

0 commit comments

Comments
 (0)