Initial commit
This commit is contained in:
parent
d5804ab210
commit
da434b7553
11 changed files with 17461 additions and 0 deletions
50
about.html
Normal file
50
about.html
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>eEVee Tracker</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='navigation' style='overflow:auto;'>
|
||||||
|
<div style='float:left;padding:10px;'><a href='index.html'>Tracker</a></div><div style='float:left;padding:10px;'><a href='about.html'>About</a></div>
|
||||||
|
</div>
|
||||||
|
<h1>About</h1>
|
||||||
|
<h2>The eEVee Tracker</h2>
|
||||||
|
<p>This tool is designed as an aide for Pokémon trainers willing to EV train their new mons. Simply add all of your relevant mons to the list of known mons and put them in your party when you train them.</p>
|
||||||
|
<p>To add your Pokémon, you need to enter a few details:
|
||||||
|
<ul>
|
||||||
|
<li><b>Name:</b> How to call your Pokémon. This may be a species name, a nickname, or anything else you wish. The only important thing is that you recognize it and that it is unique within the list of your known mons, since this is how you distinguish them.</li>
|
||||||
|
<li><b>Current EVs:</b> What are its EVs right now? If it is newly hatched or caught, they are all 0. You can leave all fields empty to set 0 EVs.</li>
|
||||||
|
<li><b>Target EVs:</b> What EVs are you aiming for? Again, you can leave all fields representing a 0 target empty.</li>
|
||||||
|
<li><b>Pokérus:</b> Does your Pokémon have the Pokérus virus? If you don't know, the answer is probably no.</li>
|
||||||
|
<li><b>Held Item: </b> If you use a relevant held item (that is, one that affects EV gains), select it here. Otherwise, leave it at "No relevant one".</li>
|
||||||
|
</ul>
|
||||||
|
You can change all of this later from the Current Party or Known Pokémon views by using the Edit button.</p>
|
||||||
|
<p>Below the Current Party table, you can search for and fight opponents. Once you select the Fight button, you are prompted as to whether you won. If you click cancel, nothing happens (this is in order to avoid accidental issuance of EVs on a missclick). If you press OK, the appropriate amount of EV will be added to all Pokémon in your current party, and the opponent is shifted to the top of the table for quick reference.</p>
|
||||||
|
<p>You can feed your Pokémon Berries, Vitamins, or use Feathers via the <b>Use Item</b> button.</p>
|
||||||
|
<h2>Importing and Exporting</h2>
|
||||||
|
<p>You can generate a JSON export of your current state using the <b>Export Data</b> button. Back this up as a text file, if it is important for you and you suspect that your browser's Local Storage might be cleared. You can also send it to another device to continue playing there. If you paste that same text into the textfield behind the <b>Import Data</b> button and use the <b>Import</b> button there, the saved state is restored. This way, you can for instance save the EVs your Pokémon have once you save the game on your console. Now, when realise you messed up the training, you can reload the game, restore the state here and try again.</p>
|
||||||
|
<p>You can of course edit the exported JSON in order to modify the party in this tracker. Here is what a typical export looks like:</p>
|
||||||
|
<code>
|
||||||
|
{"mons":[{"name":"Bulbasaur","current_evs":[0,3,1,74,2,0],"target_evs":[0,0,0,100,100,0],"pokerus":false,"held_item":"Power Lens"},{"name":"Charmander","current_evs":[0,6,2,6,0,80],"target_evs":[0,0,0,100,0,100],"pokerus":true,"held_item":"Power Anklet"},{"name":"Squirtle","current_evs":[0,0,24,7,2,0],"target_evs":[0,0,100,0,100,0],"pokerus":false,"held_item":"Power Belt"}],"party":[1,0]}
|
||||||
|
</code>
|
||||||
|
<p>The JSON object contains two keys: <code>mons</code> and <code>party</code>.</p>
|
||||||
|
<p><code>mons</code> is an array of all the known Pokémon. Each one of them holds keys corresponding to the data fields you can set in the Add and Edit menues:</p>
|
||||||
|
<table>
|
||||||
|
<tr></tr><td>Name</td><td>Allowed values</td><td>Description</td></tr>
|
||||||
|
<tr><td><code>name</code></td><td>Any String; must be unique among your <code>mons</code>.</td><td>How to call your Pokémon</td></tr>
|
||||||
|
<tr><td><code>current_evs</code></td><td>Array of 6 integers within the allowed values for EVs in this generation</td><td>this Pokémon's current EVs</td></tr>
|
||||||
|
<tr><td><code>target_evs</code></td><td>Array of 6 integers within the allowed values for EVs in this generation</td><td>this Pokémon's desired EVs</td></tr>
|
||||||
|
<tr><td><code>pokerus</code></td><td><code>true</code> or <code>false</code></td><td>whether or not this Pokémon is affected by the Pokérus virus</td></tr>
|
||||||
|
<tr><td><code>held_item</code></td><td>Any String</td><td>The item your Pokémon is currently holding. Will be set to an empty String if the value doesn't correspond to an item known to affect EV training in this generation of Pokémon games.</td></tr>
|
||||||
|
<p><code>party</code> is an array holding the indices of your known Pokémon that are in your current party. As usual in programming, counting starts at 0. So, in the above example, The party consists of the second and first known Pokémon (in that order), which are Charmander and Bulbasaur in this case. If you put an invalid index here, the tool won't work properly anymore.</p>
|
||||||
|
</table>
|
||||||
|
<p>If you edited your state and encountered an error, you can probably still extract the data from your browser's Local Storage by using its developer tools. Google for that. Otherwise, you need to start from your last backup. Clear the local storage, try fixing your data and import them again.</p>
|
||||||
|
<h2>Data Usage</h2>
|
||||||
|
<p>The eEVee Tracker runs entirely in your browser. The hosting server receives no data whatsoever about your Pokémon, their Items and Opponents. For this reason, you are responsible for saving your data and syncing it with other devices. No matter how nicely you ask, it is technically impossible for the server operator to restore lost data.</p>
|
||||||
|
<p>There are no cookie banners here, because this tool doesn't use any cookies. All the data is saved in your browser's local storage. You are in charge of it.</p>
|
||||||
|
<p>The server does receive a request upon each load and refresh of a site (one of the links at the top), unless it is being served from your cache. This request contains your IP address, but no further personal information. On burnus.net, successful requests are not being logged, but errors are. Everything else you do in this tool (editing your Pokémon/Party, using Items, fightin Opponents, importing and exporting) does not interact with the server and therefore doesn't even generate any trackable data.</p>
|
||||||
|
<h2>Prior Art</h2>
|
||||||
|
<p>The Opponent data (EV yields) are extracted from the <a href="https://github.com/PokeAPI/pokeapi/">PokeAPI Github Repository</a> and is provided under the <a href="pokeapi-license.txt">BSD-3-clause license</a>.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
1303
data/pokemon.csv
Normal file
1303
data/pokemon.csv
Normal file
File diff suppressed because it is too large
Load diff
7813
data/pokemon_stats.csv
Normal file
7813
data/pokemon_stats.csv
Normal file
File diff suppressed because it is too large
Load diff
19
index.html
Normal file
19
index.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>eEVee Tracker</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='navigation' style='overflow:auto;'>
|
||||||
|
<div style='float:left;padding:10px;'><a href='index.html'>Tracker</a></div><div style='float:left;padding:10px;'><a href='about.html'>About</a></div>
|
||||||
|
</div>
|
||||||
|
<h1>Hello Trainer</h1>
|
||||||
|
<div id="main_area"></div>
|
||||||
|
<div id="opponent_search_field" style="margin-top:20px">
|
||||||
|
<label for='opponent'>Opponent:</label><input type=text id='opponent' onkeyup='render_opponents()' size=42><br>
|
||||||
|
</div>
|
||||||
|
<div id="opponents_area"> </div>
|
||||||
|
<script type="text/javascript" src="js/eevee.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
499
js/eevee.js
Normal file
499
js/eevee.js
Normal file
|
@ -0,0 +1,499 @@
|
||||||
|
const EV_NAMES=["HP", "Atk", "Def", "SpA", "SpD", "Spe"];
|
||||||
|
|
||||||
|
var mons = JSON.parse(localStorage.getItem('mons'));
|
||||||
|
if (!mons) {
|
||||||
|
mons = [];
|
||||||
|
}
|
||||||
|
var party = JSON.parse(localStorage.getItem('party'));
|
||||||
|
if (!party) {
|
||||||
|
party = [];
|
||||||
|
}
|
||||||
|
var gameData;
|
||||||
|
var opponents;
|
||||||
|
var overwriting = false;
|
||||||
|
|
||||||
|
fetch('js/game_data.json')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
setGame(data);
|
||||||
|
render_party();
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error loading JSON:', error));
|
||||||
|
|
||||||
|
fetch ('js/opponents.json')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
setOpponents(data);
|
||||||
|
render_opponents();
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error loading JSON:', error));
|
||||||
|
|
||||||
|
function setOpponents(data) {
|
||||||
|
opponents = data.mons;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setGame(data) {
|
||||||
|
gameData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stash(i) {
|
||||||
|
party.splice(i, 1);
|
||||||
|
render_party();
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_to_party(i) {
|
||||||
|
if (!party || party.length == 0) {
|
||||||
|
party = [i];
|
||||||
|
} else {
|
||||||
|
party.push(i);
|
||||||
|
}
|
||||||
|
localStorage.setItem('party', "[" + party + "]");
|
||||||
|
render_known();
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_mon(mon) {
|
||||||
|
let out = "<td>" + mon.name + "</td>";
|
||||||
|
for (let ev=0; ev<6; ev++) {
|
||||||
|
let curr = mon.current_evs[ev];
|
||||||
|
let tgt = mon.target_evs[ev];
|
||||||
|
if (curr < tgt) {
|
||||||
|
out += "<td><font color=\"blue\">" + curr + "/" + tgt + "(-" + (tgt - curr) + ")" + "</font></td>";
|
||||||
|
} else if (tgt < curr) {
|
||||||
|
out += "<td><font color=\"red\">" + curr + "/" + tgt + "(+" + (curr - tgt) + ")" + "</font></td>";
|
||||||
|
} else {
|
||||||
|
out += "<td><font color=\"grey\">" + curr + "</font></td>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out += "<td>";
|
||||||
|
if (mon.pokerus) {
|
||||||
|
out += "🦠";
|
||||||
|
}
|
||||||
|
out += "</td><td>" + render_item(mon.held_item) + "</td>";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function edit_mon(mon_idx, return_to_party) {
|
||||||
|
let mon = mons[mon_idx];
|
||||||
|
new_mon(return_to_party);
|
||||||
|
document.getElementById("opponents_area").hidden = true;
|
||||||
|
document.getElementById("opponent_search_field").hidden = true;
|
||||||
|
document.getElementById("name").value = mon.name;
|
||||||
|
document.getElementById("curr_hp").value = mon.current_evs[0];
|
||||||
|
document.getElementById("curr_atk").value = mon.current_evs[1];
|
||||||
|
document.getElementById("curr_def").value = mon.current_evs[2];
|
||||||
|
document.getElementById("curr_spa").value = mon.current_evs[3];
|
||||||
|
document.getElementById("curr_spd").value = mon.current_evs[4];
|
||||||
|
document.getElementById("curr_spe").value = mon.current_evs[5];
|
||||||
|
document.getElementById("tgt_hp").value = mon.target_evs[0];
|
||||||
|
document.getElementById("tgt_atk").value = mon.target_evs[1];
|
||||||
|
document.getElementById("tgt_def").value = mon.target_evs[2];
|
||||||
|
document.getElementById("tgt_spa").value = mon.target_evs[3];
|
||||||
|
document.getElementById("tgt_spd").value = mon.target_evs[4];
|
||||||
|
document.getElementById("tgt_spe").value = mon.target_evs[5];
|
||||||
|
document.getElementById("pokerus").checked = mon.pokerus;
|
||||||
|
document.getElementById("item").value = mon.held_item;
|
||||||
|
overwriting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function new_mon(return_to_party) {
|
||||||
|
overwriting = false;
|
||||||
|
let out = "<table id='new_mon'>" +
|
||||||
|
"<tr><td><label for='name'>Name: </label></td>" +
|
||||||
|
"<td colspan='6'><input type='text' id='name'></td></tr>" +
|
||||||
|
"<tr><th></th><th>HP</th><th>Atk</th><th>Def</th><th>SpA</th><th>SpD</th><th>Spe</th></tr>" +
|
||||||
|
"<tr><td><label for='curr_hp'>Current EVs: </label></td>" +
|
||||||
|
"<td><input type='text' id='curr_hp' size=3></td>" +
|
||||||
|
"<td><input type='text' id='curr_atk' size=3></td>" +
|
||||||
|
"<td><input type='text' id='curr_def' size=3></td>" +
|
||||||
|
"<td><input type='text' id='curr_spa' size=3></td>" +
|
||||||
|
"<td><input type='text' id='curr_spd' size=3></td>" +
|
||||||
|
"<td><input type='text' id='curr_spe' size=3></td></tr>" +
|
||||||
|
"<tr><td><label for='tgt_hp'>Target EVs: </label></td>" +
|
||||||
|
"<td><input type='text' id='tgt_hp' size=3></td>" +
|
||||||
|
"<td><input type='text' id='tgt_atk' size=3></td>" +
|
||||||
|
"<td><input type='text' id='tgt_def' size=3></td>" +
|
||||||
|
"<td><input type='text' id='tgt_spa' size=3></td>" +
|
||||||
|
"<td><input type='text' id='tgt_spd' size=3></td>" +
|
||||||
|
"<td><input type='text' id='tgt_spe' size=3></td></tr>" +
|
||||||
|
"<tr><td><label for='pokerus'>Pokérus? </label></td>" +
|
||||||
|
"<td><input type='checkbox' id='pokerus'></td></tr>" +
|
||||||
|
"<tr><td><label for='item'>Held Item: </label></td>" +
|
||||||
|
"<td colspan='6'><select id='item'><option value=''>No relevant one</option>";
|
||||||
|
for (let i=0; i<gameData.adding_items.length; i++) {
|
||||||
|
let item = gameData.adding_items[i].name;
|
||||||
|
out += "<option value='" + item + "'>" + render_item(item) + "</option>";
|
||||||
|
}
|
||||||
|
for (let i=0; i<gameData.multiplying_items.length; i++) {
|
||||||
|
let item = gameData.multiplying_items[i].name;
|
||||||
|
out += "<option value='" + item + "'>" + render_item(item) + "</option>";
|
||||||
|
}
|
||||||
|
out += "</select></td></tr>" +
|
||||||
|
"</table><button onclick='try_add_mon(" + return_to_party + ")'>Validate</button>" +
|
||||||
|
"<button onclick='";
|
||||||
|
if (return_to_party) {
|
||||||
|
out += "render_party()";
|
||||||
|
} else {
|
||||||
|
out += "render_known()";
|
||||||
|
}
|
||||||
|
out += "'>Back</button>";
|
||||||
|
document.getElementById("main_area").innerHTML = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_item(name) {
|
||||||
|
let res = "No relevant item";
|
||||||
|
for (let i=0; i<gameData.adding_items.length; i++) {
|
||||||
|
let item = gameData.adding_items[i];
|
||||||
|
if (item.name == name) {
|
||||||
|
return name + " (" + EV_NAMES[item.ev_idx] + " +" + item.ev_added + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i=0; i<gameData.multiplying_items.length; i++) {
|
||||||
|
let item = gameData.multiplying_items[i];
|
||||||
|
if (item.name == name) {
|
||||||
|
return name + " (all *" + item.multiplyer + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i=0; i<gameData.use_items.length; i++) {
|
||||||
|
let item = gameData.use_items[i];
|
||||||
|
if (item.name == name) {
|
||||||
|
let res = name + " (" + EV_NAMES[item.ev_idx];
|
||||||
|
if (item.ev_added > 0) {
|
||||||
|
res += " +";
|
||||||
|
} else {
|
||||||
|
res += " ";
|
||||||
|
}
|
||||||
|
return res + item.ev_added + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function feed(mon_idx) {
|
||||||
|
console.log("Feed");
|
||||||
|
let mon = mons[party[mon_idx]];
|
||||||
|
let item_name = document.getElementById('item').value;
|
||||||
|
let item;
|
||||||
|
for (let i=0; i<gameData.use_items.length; i++) {
|
||||||
|
if (item_name == gameData.use_items[i].name) {
|
||||||
|
item = gameData.use_items[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let count = Number.parseInt(document.getElementById('count').value, 10);
|
||||||
|
if (!Number.isNaN(count)) {
|
||||||
|
let evs_added = [0, 0, 0, 0, 0, 0];
|
||||||
|
evs_added[item.ev_idx] += item.ev_added;
|
||||||
|
add_ev(mon, evs_added, count);
|
||||||
|
}
|
||||||
|
use_item(mon_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
function try_add_mon(return_to_party) {
|
||||||
|
let name = document.getElementById('name').value;
|
||||||
|
if (name == "") {
|
||||||
|
alert("Name must not be empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let current_evs = [
|
||||||
|
Number.parseInt(document.getElementById('curr_hp').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('curr_atk').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('curr_def').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('curr_spa').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('curr_spd').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('curr_spe').value, 10),
|
||||||
|
];
|
||||||
|
let total_curr_evs = 0;
|
||||||
|
for (let i=0; i<6; i++) {
|
||||||
|
if (Number.isNaN(current_evs[i])) {
|
||||||
|
current_evs[i] = 0;
|
||||||
|
}
|
||||||
|
if (current_evs[i] < 0 || current_evs[i] > gameData.max_ev_value) {
|
||||||
|
alert("Current EV value for " + EV_NAMES[i] + " is outside the allowed range for " + gameData.name + ": (0..=" + gameData.max_ev_value + ").");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
total_curr_evs += current_evs[i];
|
||||||
|
}
|
||||||
|
if (total_curr_evs > gameData.max_total_evs) {
|
||||||
|
alert("Total current EVs are " + total_curr_evs + ", which is higher than the maximum for " + gameData.name + ": " + gameData.max_total_evs + ".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let target_evs = [
|
||||||
|
Number.parseInt(document.getElementById('tgt_hp').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('tgt_atk').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('tgt_def').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('tgt_spa').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('tgt_spd').value, 10),
|
||||||
|
Number.parseInt(document.getElementById('tgt_spe').value, 10),
|
||||||
|
];
|
||||||
|
let total_tgt_evs = 0;
|
||||||
|
for (let i=0; i<6; i++) {
|
||||||
|
if (Number.isNaN(target_evs[i])) {
|
||||||
|
target_evs[i] = 0;
|
||||||
|
}
|
||||||
|
if (target_evs[i] < 0 || target_evs[i] > gameData.max_ev_value) {
|
||||||
|
alert("target EV value for " + EV_NAMES[i] + " is outside the allowed range for " + gameData.name + ": (0..=" + gameData.max_ev_value + ").");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
total_tgt_evs += target_evs[i];
|
||||||
|
}
|
||||||
|
if (total_tgt_evs > gameData.max_total_evs) {
|
||||||
|
alert("Total target EVs are " + total_tgt_evs + ", which is higher than the maximum for " + gameData.name + ": " + gameData.max_total_evs + ".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let pokerus = document.getElementById('pokerus').checked;
|
||||||
|
let held_item = document.getElementById('item').value;
|
||||||
|
let mon = {
|
||||||
|
name: name,
|
||||||
|
current_evs: current_evs,
|
||||||
|
target_evs: target_evs,
|
||||||
|
pokerus: pokerus,
|
||||||
|
held_item: held_item,
|
||||||
|
};
|
||||||
|
for (let i=0; i<mons.length; i++) {
|
||||||
|
if (mons[i].name == name) {
|
||||||
|
if (overwriting) {
|
||||||
|
mons[i] = mon;
|
||||||
|
localStorage.setItem('mons', JSON.stringify(mons));
|
||||||
|
if (return_to_party) {
|
||||||
|
render_party();
|
||||||
|
} else {
|
||||||
|
render_known();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
alert("You already have a Pokémon by that name. Please choose another one.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mons.push(mon);
|
||||||
|
localStorage.setItem('mons', JSON.stringify(mons));
|
||||||
|
if (return_to_party) {
|
||||||
|
render_party();
|
||||||
|
} else {
|
||||||
|
render_known();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_known() {
|
||||||
|
let out = "<h2>Known:</h2><table>";
|
||||||
|
if (mons.length == 0 || mons.length == party.length) {
|
||||||
|
out += "None";
|
||||||
|
} else if (party.length >= gameData.affected_mons) {
|
||||||
|
out += "Party is full";
|
||||||
|
} else {
|
||||||
|
out += "<tr><th>Name</th><th>HP</th><th>Atk</th><th>Def</th><th>SpA</th><th>SpD</th><th>Spe</th><th>Pokérus</th><th>Item</th></tr>";
|
||||||
|
for (let i=mons.length-1; i>=0; i--) {
|
||||||
|
if (party.includes(i)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out += "<tr>";
|
||||||
|
out += render_mon(mons[i]);
|
||||||
|
out += "<td><button onclick='add_to_party(" + i + ")'>Add</button></td>";
|
||||||
|
out += "<td><button onclick='edit_mon(" + i + ", false)'>Edit</button></td>";
|
||||||
|
out += "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
out += "</table>";
|
||||||
|
}
|
||||||
|
out += "<br><button onclick='new_mon()'>New</button>";
|
||||||
|
out += "<br><button onclick='render_party()'>Back</button>";
|
||||||
|
document.getElementById("main_area").innerHTML = out;
|
||||||
|
document.getElementById("opponents_area").hidden = true;
|
||||||
|
document.getElementById("opponent_search_field").hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_party() {
|
||||||
|
let out = "<h2>Current Party:</h2><table>";
|
||||||
|
if (party.length == 0) {
|
||||||
|
out += "Empty";
|
||||||
|
} else {
|
||||||
|
out += "<tr><th>Name</th><th>HP</th><th>Atk</th><th>Def</th><th>SpA</th><th>SpD</th><th>Spe</th><th>Pokérus</th><th>Item</th></tr>";
|
||||||
|
for (let i=0; i<party.length; i++) {
|
||||||
|
out += "<tr>";
|
||||||
|
out += render_mon(mons[party[i]]);
|
||||||
|
out += "<td><button onclick='stash(" + i + ")'>Stash</button> ";
|
||||||
|
out += "<button onclick='use_item(" + i + ")'>Use Item</button> ";
|
||||||
|
out += "<button onclick='edit_mon(" + party[i] + ", true)'>Edit</button></td>";
|
||||||
|
out += "</tr>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out += "</table>";
|
||||||
|
out += "<br><button onclick='render_known()'>Add</button> ";
|
||||||
|
out += "<button onclick='export_data()'>Export Data</button> ";
|
||||||
|
out += "<button onclick='render_import()'>Import Data</button>";
|
||||||
|
document.getElementById("main_area").innerHTML = out;
|
||||||
|
document.getElementById("opponents_area").hidden = false;
|
||||||
|
document.getElementById("opponent_search_field").hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function export_data() {
|
||||||
|
let save_data = {
|
||||||
|
mons: mons,
|
||||||
|
party: party,
|
||||||
|
};
|
||||||
|
document.getElementById("opponents_area").hidden = true;
|
||||||
|
document.getElementById("opponent_search_field").hidden = true;
|
||||||
|
document.getElementById("main_area").innerHTML = "<p>Copy the contents of the following text area and save them on your device. You can paste them into the text area shown by the Import function to update your local data. Modify them in between if you like, but don't blame me if you break anything. If so, you may have to reset your browser's Local Storage.</p>" +
|
||||||
|
"<textarea id='data' type='text' style='width:100%;height:auto'></textarea><br>" +
|
||||||
|
"<button onclick='render_party()'>Back</button>";
|
||||||
|
let field = document.getElementById("data");
|
||||||
|
field.value = JSON.stringify(save_data);
|
||||||
|
field.select();
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_import() {
|
||||||
|
document.getElementById("opponents_area").hidden = true;
|
||||||
|
document.getElementById("opponent_search_field").hidden = true;
|
||||||
|
document.getElementById("main_area").innerHTML = "<p>Paste your exported data into this field. If it wasn't modified, it should restore your state fine. If you did modify it, make sure it is still well-formated. If importing breaks your state, reset your browser's Local Storage and try to fix your data.</p>" +
|
||||||
|
"<textarea id='data' type='text' style='width:100%;height:auto'></textarea><br>" +
|
||||||
|
"<button onclick='try_import_data()'>Import</button>" +
|
||||||
|
"<button onclick='render_party()'>Back</button>";
|
||||||
|
}
|
||||||
|
|
||||||
|
function try_import_data () {
|
||||||
|
let save_data = JSON.parse(document.getElementById("data").value);
|
||||||
|
if (!save_data.mons) {
|
||||||
|
alert("Value for 'mons' not set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!save_data.party) {
|
||||||
|
alert("Value for 'party' not set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mons = save_data.mons;
|
||||||
|
party = save_data.party;
|
||||||
|
render_party();
|
||||||
|
localStorage.setItem('mons', JSON.stringify(mons));
|
||||||
|
localStorage.setItem('party', "[" + party + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
function use_item(mon_idx) {
|
||||||
|
let mon = mons[party[mon_idx]];
|
||||||
|
let out = "<h2>Currently feeding</h2><table>" +
|
||||||
|
"<tr><th>Name</th><th>HP</th><th>Atk</th><th>Def</th><th>SpA</th><th>SpD</th><th>Spe</th><th>Item</th></tr><tr>" +
|
||||||
|
render_mon(mon) + "</tr></table><table><tr><td><label for='item'>Item: </label></td>" +
|
||||||
|
"<td><select id='item'>";
|
||||||
|
for (let i=0; i<gameData.use_items.length; i++) {
|
||||||
|
let item = gameData.use_items[i].name;
|
||||||
|
out += "<option value='" + item + "'>" + render_item(item) + "</option>";
|
||||||
|
}
|
||||||
|
out += "</td></tr><tr><td><label for='count'>Count: </label></td>" +
|
||||||
|
"<td><input type='text' id='count' size=3></td></tr>" +
|
||||||
|
"<tr><td><button onclick='feed(" + mon_idx + ")'>Use Item</button></td></tr>" +
|
||||||
|
"<tr><td><button onclick='render_party()'>Back</button></td></tr></table>";
|
||||||
|
document.getElementById("main_area").innerHTML = out;
|
||||||
|
document.getElementById("opponents_area").hidden = true;
|
||||||
|
document.getElementById("opponent_search_field").hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_ev(mon, added_evs, count) {
|
||||||
|
let curr = [...mon.current_evs];
|
||||||
|
let total = 0;
|
||||||
|
let changed = [];
|
||||||
|
for (let idx=0; idx<6; idx++) {
|
||||||
|
let new_ev = curr[idx] + added_evs[idx] * count;
|
||||||
|
if (new_ev < 0) {
|
||||||
|
new_ev = 0;
|
||||||
|
}
|
||||||
|
if (new_ev > gameData.max_ev_value) {
|
||||||
|
new_ev = gameData.max_ev_value;
|
||||||
|
}
|
||||||
|
if (new_ev != curr[idx]) {
|
||||||
|
curr[idx] = new_ev;
|
||||||
|
changed.push(idx);
|
||||||
|
}
|
||||||
|
total += new_ev;
|
||||||
|
}
|
||||||
|
if (total > gameData.max_total_evs) {
|
||||||
|
if (changed.length == 1) {
|
||||||
|
curr[changed[0]] -= total - gameData.max_total_evs;
|
||||||
|
} else {
|
||||||
|
let raised_evs = EV_NAMES[changed[0]];
|
||||||
|
for (let idx=1; idx<changed.length; idx++) {
|
||||||
|
raised_evs += ", " + EV_NAMES[changed[idx]];
|
||||||
|
}
|
||||||
|
alert("Ambiguous result trying to add " + added_evs + " to " + mon.name + ".\nTotal EVs would exceed this generation's maximum, so they must be reduced. However, it is unclear, which EV is being reduced. It could be any of:\n" + raised_evs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mon.current_evs = curr;
|
||||||
|
localStorage.setItem('mons', JSON.stringify(mons));
|
||||||
|
}
|
||||||
|
|
||||||
|
String.prototype.fuzzy = function (s) {
|
||||||
|
var hay = this.toLowerCase(), i = 0, n = -1, l;
|
||||||
|
s = s.toLowerCase();
|
||||||
|
for (; l = s[i++] ;) if (!~(n = hay.indexOf(l, n + 1))) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
function fight(opp_idx) {
|
||||||
|
if (party.length == 0) {
|
||||||
|
alert("Can't fight with an empty party. Please add some Pokémon.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let name = opponents[opp_idx].name;
|
||||||
|
let ev_yield = opponents[opp_idx].ev_yield;
|
||||||
|
if (confirm("Fighting " + name + ". Defeated?") == true) {
|
||||||
|
opponents.splice(opp_idx, 1);
|
||||||
|
opponents.unshift({ name: name, ev_yield: ev_yield });
|
||||||
|
|
||||||
|
for (let i=0; i<party.length; i++) {
|
||||||
|
let mon = mons[party[i]];
|
||||||
|
let evs = [...ev_yield];
|
||||||
|
let multiplyer = 1.0;
|
||||||
|
if (mon.pokerus) {
|
||||||
|
multiplyer = gameData.pokerus_multiplyer;
|
||||||
|
}
|
||||||
|
for (let j=0; j<gameData.adding_items.length;j++) {
|
||||||
|
let item = gameData.adding_items[j];
|
||||||
|
if (item.name == mon.held_item) {
|
||||||
|
evs[item.ev_idx] += item.ev_added;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j=0; j<gameData.multiplying_items.length;j++) {
|
||||||
|
let item = gameData.multiplying_items[j];
|
||||||
|
if (item.name == mon.held_item) {
|
||||||
|
multiplyer *= item.multiplyer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_ev(mon, evs, multiplyer);
|
||||||
|
}
|
||||||
|
document.getElementById('opponent').value = "";
|
||||||
|
render_party();
|
||||||
|
render_opponents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_opponents() {
|
||||||
|
let search_string = document.getElementById('opponent').value;
|
||||||
|
let found = [];
|
||||||
|
for (let i=0; i<opponents.length; i++) {
|
||||||
|
if (opponents[i].name.fuzzy(search_string)) {
|
||||||
|
found.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = "<table><tr><th>Name</th>" +
|
||||||
|
"<th>HP</th><th>Atk</th><th>Def</th><th>SpA</th><th>SpD</th><th>Spe</th>" +
|
||||||
|
"<th></th></tr>";
|
||||||
|
for (let i=0; i<found.length && i<50; i++) {
|
||||||
|
let name = opponents[found[i]].name;
|
||||||
|
let ev_yield = opponents[found[i]].ev_yield;
|
||||||
|
res += "<tr><td>" + name + "</td><td>" +
|
||||||
|
ev_yield[0] + "</td><td>" +
|
||||||
|
ev_yield[1] + "</td><td>" +
|
||||||
|
ev_yield[2] + "</td><td>" +
|
||||||
|
ev_yield[3] + "</td><td>" +
|
||||||
|
ev_yield[4] + "</td><td>" +
|
||||||
|
ev_yield[5] + "</td><td>" +
|
||||||
|
"<button onclick='fight(" + found[i] + ")'>Fight</input></td></tr>";
|
||||||
|
}
|
||||||
|
res += "</table>";
|
||||||
|
document.getElementById("opponents_area").innerHTML = res;
|
||||||
|
}
|
137
js/game_data.js
Normal file
137
js/game_data.js
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
{
|
||||||
|
"name": "Gen 8/9",
|
||||||
|
affected_mons: 6,
|
||||||
|
"max_ev_value": 252,
|
||||||
|
"max_total_evs": 510,
|
||||||
|
pokerus_multiplyer: 2,
|
||||||
|
"adding_items": [
|
||||||
|
{
|
||||||
|
"name": "Power Weight",
|
||||||
|
"ev_idx": 0,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Bracer",
|
||||||
|
"ev_idx": 1,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Belt",
|
||||||
|
"ev_idx": 2,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Lens",
|
||||||
|
"ev_idx": 3,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Band",
|
||||||
|
"ev_idx": 4,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Anklet",
|
||||||
|
"ev_idx": 5,
|
||||||
|
"ev_added": 8
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"multiplying_items": [
|
||||||
|
{
|
||||||
|
"name": "Macho Brace",
|
||||||
|
"multiplyer": 2.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"use_items": [
|
||||||
|
{
|
||||||
|
"name": "HP Up",
|
||||||
|
"ev_idx": 0,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Protein",
|
||||||
|
"ev_idx": 1,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Iron",
|
||||||
|
"ev_idx": 2,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Calcium",
|
||||||
|
"ev_idx": 3,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Zinc",
|
||||||
|
"ev_idx": 4,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Carbos",
|
||||||
|
"ev_idx": 5,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Health Feather",
|
||||||
|
"ev_idx": 0,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Muscle Feather",
|
||||||
|
"ev_idx": 1,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Resist Feather",
|
||||||
|
"ev_idx": 2,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Genius Feather",
|
||||||
|
"ev_idx": 3,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Clever Feather",
|
||||||
|
"ev_idx": 4,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Swift Feather",
|
||||||
|
"ev_idx": 5,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pomeg Berry",
|
||||||
|
"ev_idx": 0,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kelpsy Berry",
|
||||||
|
"ev_idx": 1,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Qualot Berry",
|
||||||
|
"ev_idx": 2,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hondew Berry",
|
||||||
|
"ev_idx": 3,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Grepa Berry",
|
||||||
|
"ev_idx": 4,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tamato Berry",
|
||||||
|
"ev_idx": 5,
|
||||||
|
"ev_added": -10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
137
js/game_data.json
Normal file
137
js/game_data.json
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
{
|
||||||
|
"name": "Gen 8/9",
|
||||||
|
"affected_mons": 6,
|
||||||
|
"max_ev_value": 252,
|
||||||
|
"max_total_evs": 510,
|
||||||
|
"pokerus_multiplyer": 2,
|
||||||
|
"adding_items": [
|
||||||
|
{
|
||||||
|
"name": "Power Weight",
|
||||||
|
"ev_idx": 0,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Bracer",
|
||||||
|
"ev_idx": 1,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Belt",
|
||||||
|
"ev_idx": 2,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Lens",
|
||||||
|
"ev_idx": 3,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Band",
|
||||||
|
"ev_idx": 4,
|
||||||
|
"ev_added": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Anklet",
|
||||||
|
"ev_idx": 5,
|
||||||
|
"ev_added": 8
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"multiplying_items": [
|
||||||
|
{
|
||||||
|
"name": "Macho Brace",
|
||||||
|
"multiplyer": 2.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"use_items": [
|
||||||
|
{
|
||||||
|
"name": "HP Up",
|
||||||
|
"ev_idx": 0,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Protein",
|
||||||
|
"ev_idx": 1,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Iron",
|
||||||
|
"ev_idx": 2,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Calcium",
|
||||||
|
"ev_idx": 3,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Zinc",
|
||||||
|
"ev_idx": 4,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Carbos",
|
||||||
|
"ev_idx": 5,
|
||||||
|
"ev_added": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Health Feather",
|
||||||
|
"ev_idx": 0,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Muscle Feather",
|
||||||
|
"ev_idx": 1,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Resist Feather",
|
||||||
|
"ev_idx": 2,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Genius Feather",
|
||||||
|
"ev_idx": 3,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Clever Feather",
|
||||||
|
"ev_idx": 4,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Swift Feather",
|
||||||
|
"ev_idx": 5,
|
||||||
|
"ev_added": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pomeg Berry",
|
||||||
|
"ev_idx": 0,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kelpsy Berry",
|
||||||
|
"ev_idx": 1,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Qualot Berry",
|
||||||
|
"ev_idx": 2,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hondew Berry",
|
||||||
|
"ev_idx": 3,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Grepa Berry",
|
||||||
|
"ev_idx": 4,
|
||||||
|
"ev_added": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tamato Berry",
|
||||||
|
"ev_idx": 5,
|
||||||
|
"ev_added": -10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
5212
js/opponents.json
Normal file
5212
js/opponents.json
Normal file
File diff suppressed because it is too large
Load diff
13
pokeapi-license.txt
Normal file
13
pokeapi-license.txt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Copyright (c) © 2013–2023 Paul Hallett and PokéAPI contributors (https://github.com/PokeAPI/pokeapi#contributing). Pokémon and Pokémon character names are trademarks of Nintendo.
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of PokéAPI nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2207
style-db.css
Normal file
2207
style-db.css
Normal file
File diff suppressed because it is too large
Load diff
71
style.css
Normal file
71
style.css
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
* {
|
||||||
|
box-sizing:border-box
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
min-height: 100%;
|
||||||
|
color: #404040;
|
||||||
|
font-family: Ubuntu, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
|
text-size-adjust:none;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-device-width: 480px) {
|
||||||
|
html {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 1em;
|
||||||
|
padding: 0;
|
||||||
|
font-size:1rem
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, p, dl, pre {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
padding:0
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding:4px 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
font-weight:bold
|
||||||
|
}
|
||||||
|
|
||||||
|
input, button, select, option, textarea {
|
||||||
|
margin: 0;
|
||||||
|
padding: .5rem .75rem;
|
||||||
|
color: inherit;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new_mon {
|
||||||
|
td {
|
||||||
|
padding: 1px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
padding: .5rem;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue