Compare commits

...

6 Commits

Author SHA1 Message Date
9dd8d91ba3 pass attack side to calculator 2023-02-23 17:23:11 +09:00
568798860a fix for moves 2023-02-23 17:02:20 +09:00
e5067a1b39 some more additions related to move usage 2023-02-20 03:00:29 +09:00
d1c62f3bb7 fixed linting 2023-02-06 21:07:52 +09:00
cc6cec5640 changed string to hashmap/record for abilities 2023-02-06 21:00:04 +09:00
670a01a7fa added new button 2023-02-06 20:54:38 +09:00
7 changed files with 222 additions and 114 deletions

View File

@@ -2,6 +2,7 @@
all(not(debug_assertions), target_os = "windows"), all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows" windows_subsystem = "windows"
)] )]
use std::collections::HashMap;
use std::fs; use std::fs;
use serde_json::json; use serde_json::json;
@@ -201,7 +202,7 @@ fn increase_attack_usage(index: i64) {
fn search_learnset(index: i64) -> Vec<PokemonDataLearnset> { fn search_learnset(index: i64) -> Vec<PokemonDataLearnset> {
let connection = sqlite::open("./pokemon.db").unwrap(); let connection = sqlite::open("./pokemon.db").unwrap();
let mut learnset: Vec<PokemonDataLearnset> = vec![]; let mut learnset: Vec<PokemonDataLearnset> = vec![];
let move_query = "SELECT pl.id, pl.learnset_id, l.name, l.types, l.power, l.category FROM pokemon__learnset pl JOIN learnset l on pl.learnset_id = l.id WHERE pl.pokemon_id = ? ORDER BY usage DESC"; let move_query = "SELECT pl.id, pl.learnset_id, l.name, l.types, l.power, l.category, l.priority, pl.usage FROM pokemon__learnset pl JOIN learnset l on pl.learnset_id = l.id WHERE pl.pokemon_id = ? ORDER BY usage DESC";
for row in connection for row in connection
.prepare(move_query) .prepare(move_query)
.unwrap() .unwrap()
@@ -217,6 +218,8 @@ fn search_learnset(index: i64) -> Vec<PokemonDataLearnset> {
types: serde_json::from_str(row.read::<&str, _>("types")).unwrap_or(vec![0]), types: serde_json::from_str(row.read::<&str, _>("types")).unwrap_or(vec![0]),
power: row.read::<i64, _>("power"), power: row.read::<i64, _>("power"),
category: row.read::<i64, _>("category"), category: row.read::<i64, _>("category"),
priority: row.read::<i64, _>("priority"),
usage: row.read::<i64, _>("usage"),
}; };
learnset.push(row_result) learnset.push(row_result)
} }
@@ -241,7 +244,7 @@ fn search(index: i64) -> SearchResult {
name: row.read::<&str, _>("name").to_string(), name: row.read::<&str, _>("name").to_string(),
types: serde_json::from_str(row.read::<&str, _>("types")).unwrap_or(vec![0]), types: serde_json::from_str(row.read::<&str, _>("types")).unwrap_or(vec![0]),
thumbnail: row.read::<&str, _>("thumbnail").to_string(), thumbnail: row.read::<&str, _>("thumbnail").to_string(),
abilities: row.read::<&str, _>("abilities").to_string(), abilities: serde_json::from_str(row.read::<&str, _>("abilities")).unwrap_or(HashMap::new()),
hp: row.read::<i64, _>("hp"), hp: row.read::<i64, _>("hp"),
attack: row.read::<i64, _>("attack"), attack: row.read::<i64, _>("attack"),
defense: row.read::<i64, _>("defense"), defense: row.read::<i64, _>("defense"),
@@ -257,7 +260,7 @@ fn search(index: i64) -> SearchResult {
name: "Missigno".to_string(), name: "Missigno".to_string(),
types: vec![], types: vec![],
thumbnail: "".to_string(), thumbnail: "".to_string(),
abilities: "{}".to_string(), abilities: HashMap::new(),
hp: 0, hp: 0,
attack: 0, attack: 0,
defense: 0, defense: 0,

View File

@@ -1,3 +1,5 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
@@ -11,7 +13,7 @@ pub struct SearchResult {
pub special_attack: i64, pub special_attack: i64,
pub special_defense: i64, pub special_defense: i64,
pub speed: i64, pub speed: i64,
pub abilities: String, pub abilities: HashMap<String, String>,
pub thumbnail: String, pub thumbnail: String,
pub learnset: Vec<PokemonDataLearnset>, pub learnset: Vec<PokemonDataLearnset>,
} }
@@ -24,6 +26,8 @@ pub struct PokemonDataLearnset {
pub types: Vec<i64>, pub types: Vec<i64>,
pub power: i64, pub power: i64,
pub category: i64, pub category: i64,
pub priority: i64,
pub usage: i64,
} }
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct MoveSearchResult { pub struct MoveSearchResult {
@@ -82,7 +86,7 @@ pub struct PokemonDataToLoad {
pub name: String, pub name: String,
pub types: Vec<i64>, pub types: Vec<i64>,
pub thumbnail: String, pub thumbnail: String,
pub abilities: String, pub abilities: HashMap<String, String>,
pub hp: i64, pub hp: i64,
pub attack: i64, pub attack: i64,
pub defense: i64, pub defense: i64,

View File

@@ -9,6 +9,7 @@
let player1Data: PokemonStatus | undefined; let player1Data: PokemonStatus | undefined;
let player2Data: PokemonStatus | undefined; let player2Data: PokemonStatus | undefined;
let attackId: number | undefined; let attackId: number | undefined;
let attackSide: number | undefined;
invoke("get_items").then((r: ItemData[]) => { invoke("get_items").then((r: ItemData[]) => {
items = r; items = r;
}); });
@@ -17,14 +18,31 @@
<main class="container"> <main class="container">
<div class="main-row"> <div class="main-row">
<div class="column-1"> <div class="column-1">
<MainWrapper bind:pokemonStatus={player1Data} bind:attackId {items} /> <MainWrapper
bind:pokemonStatus={player1Data}
bind:attackId
bind:attackSide
{items}
playerSide={1}
/>
</div> </div>
<div class="column-2"> <div class="column-2">
<MainWrapper bind:pokemonStatus={player2Data} bind:attackId {items} /> <MainWrapper
bind:pokemonStatus={player2Data}
bind:attackId
bind:attackSide
{items}
playerSide={2}
/>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<DamageCalculator bind:player1Data bind:player2Data bind:attackId /> <DamageCalculator
bind:player1Data
bind:player2Data
bind:attackId
bind:attackSide
/>
</div> </div>
</main> </main>

View File

@@ -7,6 +7,7 @@
export let player1Data: PokemonStatus | undefined; export let player1Data: PokemonStatus | undefined;
export let player2Data: PokemonStatus | undefined; export let player2Data: PokemonStatus | undefined;
export let attackId: number | undefined; export let attackId: number | undefined;
export let attackSide: number | undefined;
let attackData; let attackData;
$: { $: {
if (moveValue > 0) { if (moveValue > 0) {
@@ -20,6 +21,18 @@
invoke("search_move", { index: attackId }).then((r) => { invoke("search_move", { index: attackId }).then((r) => {
attackData = r; attackData = r;
attackId = undefined; attackId = undefined;
console.log(attackSide);
switch (attackSide) {
case 1: {
attack_direction = "p1p2";
break;
}
case 2: {
attack_direction = "p2p1";
break;
}
}
attackSide = undefined;
}); });
} }
} }
@@ -48,6 +61,7 @@
console.log("skip"); console.log("skip");
return; return;
} }
console.log(attackData);
if (attack_direction === "p1p2") { if (attack_direction === "p1p2") {
attacker = player1Data; attacker = player1Data;
defender = player2Data; defender = player2Data;

View File

@@ -10,6 +10,8 @@
export let items: ItemData[]; export let items: ItemData[];
export let pokemonData: PokemonData | undefined; export let pokemonData: PokemonData | undefined;
export let attackId: number | undefined; export let attackId: number | undefined;
export let attackSide: number | undefined;
export let playerSide: number;
function v_validator(v) { function v_validator(v) {
if (typeof v !== "number") { if (typeof v !== "number") {
return null; return null;
@@ -54,26 +56,36 @@
{ id: 17 }, { id: 17 },
{ id: 18 }, { id: 18 },
]; ];
function d_validator(d) { function d_validator(d, prev) {
if (typeof d !== "number") { if (typeof d !== "number") {
return null; return null;
} }
if (d > 252) { let result = 0;
return 252; if (d > prev) {
result = Math.ceil(d / 4) * 4;
} else {
result = Math.floor(d / 4) * 4;
} }
if (d < 0) { return Math.min(Math.max(result, 0), 252);
return 0;
}
return d;
} }
let hp_d_prev = 0;
let attack_d_prev = 0;
let defense_d_prev = 0;
let special_attack_d_prev = 0;
let special_defense_d_prev = 0;
let speed_d_prev = 0;
$: { $: {
if (pokemonData) { if (pokemonData) {
if (pokemonData.terastype[0] !== selected_terastype) { if (init_flag) {
selected_terastype = pokemonData.terastype[0]; selected_terastype = pokemonData.terastype[0];
init_flag = false;
} }
if (pokemonData.item !== selected_item) { if (pokemonData.item !== selected_item) {
selected_item = pokemonData.item; selected_item = pokemonData.item;
} }
total_move_usage = pokemonData.learnset
.map((v) => v.usage)
.reduce((partialSum, a) => partialSum + a, 0);
// validator // validator
level = level_validator(level); level = level_validator(level);
pokemonData.hp_v = v_validator(pokemonData.hp_v); pokemonData.hp_v = v_validator(pokemonData.hp_v);
@@ -84,14 +96,29 @@
pokemonData.special_defense_v pokemonData.special_defense_v
); );
pokemonData.speed_v = v_validator(pokemonData.speed_v); pokemonData.speed_v = v_validator(pokemonData.speed_v);
pokemonData.hp_d = d_validator(pokemonData.hp_d);
pokemonData.attack_d = d_validator(pokemonData.attack_d); hp_d_prev = pokemonData.hp_d = d_validator(pokemonData.hp_d, hp_d_prev);
pokemonData.defense_d = d_validator(pokemonData.defense_d);
pokemonData.special_attack_d = d_validator(pokemonData.special_attack_d); attack_d_prev = pokemonData.attack_d = d_validator(
pokemonData.special_defense_d = d_validator( pokemonData.attack_d,
pokemonData.special_defense_d attack_d_prev
);
defense_d_prev = pokemonData.defense_d = d_validator(
pokemonData.defense_d,
defense_d_prev
);
special_attack_d_prev = pokemonData.special_attack_d = d_validator(
pokemonData.special_attack_d,
special_attack_d_prev
);
special_defense_d_prev = pokemonData.special_defense_d = d_validator(
pokemonData.special_defense_d,
special_defense_d_prev
);
speed_d_prev = pokemonData.speed_d = d_validator(
pokemonData.speed_d,
speed_d_prev
); );
pokemonData.speed_d = d_validator(pokemonData.speed_d);
// 性格補正 0.9/1/1.1 // 性格補正 0.9/1/1.1
let atk_p = 1; let atk_p = 1;
let def_p = 1; let def_p = 1;
@@ -135,8 +162,8 @@
} else if (!pokemonData.speed_plus && !!pokemonData.speed_minus) { } else if (!pokemonData.speed_plus && !!pokemonData.speed_minus) {
spd_p = 0.9; spd_p = 0.9;
} }
abilities = Object.keys(JSON.parse(pokemonData.abilities)); abilities = Object.keys(pokemonData.abilities);
abilities_description = Object.values(JSON.parse(pokemonData.abilities)); abilities_description = Object.values(pokemonData.abilities);
hp_final = calculate_hp( hp_final = calculate_hp(
pokemonData.hp, pokemonData.hp,
pokemonData.hp_v, pokemonData.hp_v,
@@ -306,7 +333,7 @@
return ""; return "";
} }
} }
let total_move_usage = 0;
export let hp_final = 0; export let hp_final = 0;
export let attack_final = 0; export let attack_final = 0;
export let defense_final = 0; export let defense_final = 0;
@@ -316,14 +343,15 @@
let level = 50; let level = 50;
let selected_terastype = 0; let selected_terastype = 0;
let selected_item = 0; let selected_item = 0;
let init_flag = true;
let filter_move = "";
function calculate_hp(stat, v, d) { function calculate_hp(stat, v, d) {
// floor({(種族値+個体値)×2+min(63,floor(floor(1+√努力値)÷4))}×レベル÷100)+レベル+10 // floor({(種族値+個体値)×2+min(63,floor(floor(1+√努力値)÷4))}×レベル÷100)+レベル+10
return Math.floor((stat * 2 + v + d / 4) * (level / 100) + level + 10); return Math.floor((stat * 2 + v + d / 4) * (level / 100) + level + 10);
} }
function other_stats(stat, v, d, p) { function other_stats(stat, v, d, p) {
// floor({(種族値+個体値)×2+min(63,floor(floor(1+√努力値)÷4))}×レベル÷100)+5 // floor({(種族値+個体値)×2+min(63,floor(floor(1+√努力値)÷4))}×レベル÷100)+5
return Math.floor(((stat * 2 + v + d / 4) * (level / 100) + 5) * p); return Math.floor(((stat * 2 + v + d / 4 - 1) * (level / 100) + 5) * p);
} }
let abilities = []; let abilities = [];
let abilities_description = []; let abilities_description = [];
@@ -357,8 +385,11 @@
<td style="display: flex;"> <td style="display: flex;">
<select <select
bind:value={selected_terastype} bind:value={selected_terastype}
on:change={() => on:change={(a) => {
(pokemonData.terastype = [selected_terastype])} console.log(a);
pokemonData.terastype = [selected_terastype];
console.log(selected_terastype);
}}
> >
<option value={0}> なし </option> <option value={0}> なし </option>
{#each available_type as curr_type} {#each available_type as curr_type}
@@ -414,28 +445,28 @@
<tr> <tr>
<td class="value-column"><b>HP</b></td> <td class="value-column"><b>HP</b></td>
<td class="atai-column"><b>{pokemonData.hp}</b></td> <td class="atai-column"><b>{pokemonData.hp}</b></td>
<td class="atai-column" <td class="atai-column">
><b <b>
><input <input
class="vd-input" class="vd-input"
type="number" type="number"
bind:value={pokemonData.hp_v} bind:value={pokemonData.hp_v}
min="0" min="0"
max="31" max="31"
/></b />
></td </b>
> </td>
<td class="atai-column" <td class="atai-column">
><b <b>
><input <input
class="vd-input" class="vd-input"
type="number" type="number"
bind:value={pokemonData.hp_d} bind:value={pokemonData.hp_d}
min="0" min="0"
max="252" max="252"
/></b />
></td </b>
> </td>
<td class="atai-column"><b>{hp_final}</b></td> <td class="atai-column"><b>{hp_final}</b></td>
<td class="plus-minus-column"><b>+</b></td> <td class="plus-minus-column"><b>+</b></td>
<td class="plus-minus-column"><b>-</b></td> <td class="plus-minus-column"><b>-</b></td>
@@ -443,45 +474,45 @@
<tr> <tr>
<td class="value-column"><b>ATK</b></td> <td class="value-column"><b>ATK</b></td>
<td class="atai-column"><b>{pokemonData.attack}</b></td> <td class="atai-column"><b>{pokemonData.attack}</b></td>
<td class="atai-column" <td class="atai-column">
><b <b>
><input <input
class="vd-input" class="vd-input"
type="number" type="number"
bind:value={pokemonData.attack_v} bind:value={pokemonData.attack_v}
min="0" min="0"
max="31" max="31"
/></b />
></td </b>
> </td>
<td class="atai-column" <td class="atai-column">
><b <b>
><input <input
class="vd-input" class="vd-input"
type="number" type="number"
bind:value={pokemonData.attack_d} bind:value={pokemonData.attack_d}
min="0" min="0"
max="252" max="252"
/></b />
></td </b>
> </td>
<td class="atai-column"><b>{attack_final}</b></td> <td class="atai-column"><b>{attack_final}</b></td>
<td class="atai-column" <td class="atai-column">
><b <b>
><input <input
type="checkbox" type="checkbox"
bind:checked={pokemonData.attack_plus} bind:checked={pokemonData.attack_plus}
/></b />
></td </b>
> </td>
<td class="atai-column" <td class="atai-column">
><b <b>
><input <input
type="checkbox" type="checkbox"
bind:checked={pokemonData.attack_minus} bind:checked={pokemonData.attack_minus}
/></b />
></td </b>
> </td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
{#each Array.from({ length: 6 }, (_, i) => i - 6) as i} {#each Array.from({ length: 6 }, (_, i) => i - 6) as i}
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
@@ -533,37 +564,37 @@
<tr> <tr>
<td class="value-column"><b>DEF</b></td> <td class="value-column"><b>DEF</b></td>
<td class="atai-column"><b>{pokemonData.defense}</b></td> <td class="atai-column"><b>{pokemonData.defense}</b></td>
<td class="atai-column" <td class="atai-column">
><b <b>
><input <input
class="vd-input" class="vd-input"
type="number" type="number"
bind:value={pokemonData.defense_v} bind:value={pokemonData.defense_v}
min="0" min="0"
max="31" max="31"
/></b />
></td </b>
> </td>
<td class="atai-column" <td class="atai-column">
><b <b>
><input <input
class="vd-input" class="vd-input"
type="number" type="number"
bind:value={pokemonData.defense_d} bind:value={pokemonData.defense_d}
min="0" min="0"
max="252" max="252"
/></b />
></td </b>
> </td>
<td class="atai-column"><b>{defense_final}</b></td> <td class="atai-column"><b>{defense_final}</b></td>
<td class="atai-column" <td class="atai-column">
><b <b>
><input <input
type="checkbox" type="checkbox"
bind:checked={pokemonData.defense_plus} bind:checked={pokemonData.defense_plus}
/></b />
></td </b>
> </td>
<td class="atai-column"> <td class="atai-column">
<b> <b>
<input <input
@@ -910,46 +941,63 @@
</tr> </tr>
<tr> <tr>
<td class="value-column"><b>Level</b></td> <td class="value-column"><b>Level</b></td>
<td class="atai-column" <td class="atai-column">
><input <input
class="vd-input" class="vd-input"
type="number" type="number"
bind:value={level} bind:value={level}
min="1" min="1"
max="100" max="100"
/></td />
> </td>
<td class="atai-column" /> <td class="atai-column" />
</tr> </tr>
</table> </table>
</AccordionItem> </AccordionItem>
<AccordionItem open title="技"> <AccordionItem open title="技">
<input bind:value={filter_move} type="text" />
<table class="learnset"> <table class="learnset">
{#each pokemonData.learnset as learnset} {#each pokemonData.learnset as learnset}
<tr {#if filter_move === "" || learnset.name.includes(filter_move)}
on:click={async () => { <tr
console.log("passing" + learnset.name); on:click={async () => {
attackId = learnset.learnset_id; console.log("passing" + learnset.name);
await invoke("increase_attack_usage", { index: learnset.id }); attackSide = playerSide;
pokemonData.learnset = await invoke("search_learnset", { attackId = learnset.learnset_id;
index: pokemonData.id, if (playerSide > 1) {
}); // 技の使用回数は相手の使用回数に限定する。
}} await invoke("increase_attack_usage", {
> index: learnset.id,
<td });
><img pokemonData.learnset = await invoke("search_learnset", {
src={learnset.category === 1 index: pokemonData.id,
? PhysicalIcon });
: learnset.category === 2 }
? SpecialIcon }}
: BuffIcon}
alt="a"
/></td
> >
<td>{@html generate_type(learnset.types)}</td> <td>
<td>{learnset.name}</td> <img
<td>{learnset.power}</td> src={learnset.category === 1
</tr> ? PhysicalIcon
: learnset.category === 2
? SpecialIcon
: BuffIcon}
alt="a"
/>
</td>
<td>{@html generate_type(learnset.types)}</td>
<td>{learnset.name}</td>
<td>{learnset.power}</td>
<td>{learnset.priority}</td>
<td
>{total_move_usage === 0
? 0
: Math.round(
(learnset.usage / total_move_usage) * 10000
) / 100}%</td
>
</tr>
{/if}
{/each} {/each}
</table> </table>
</AccordionItem> </AccordionItem>

View File

@@ -72,7 +72,9 @@
item: pokemonData ? pokemonData.item : 0, item: pokemonData ? pokemonData.item : 0,
}; };
} }
export let playerSide: number;
export let attackId: number | undefined; export let attackId: number | undefined;
export let attackSide: number | undefined;
export let items: ItemData[]; export let items: ItemData[];
let myValue; let myValue;
let index = 0; let index = 0;
@@ -126,7 +128,7 @@
<div class="row-display"> <div class="row-display">
<div class="pokemon-button-div"> <div class="pokemon-button-div">
<table class="button-table"> <table class="button-table">
{#each [0, 1, 2, 3, 4, 5] as i} {#each Array.from({ length: 6 }, (_, i) => i) as i}
<tr> <tr>
<td> <td>
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
@@ -179,6 +181,21 @@
> >
Load Load
</button><br /> </button><br />
<button
on:click={() => {
pokemonDataArray.forEach((pd) => {
pd.attack_buff = 0;
pd.defense_buff = 0;
pd.special_attack_buff = 0;
pd.special_defense_buff = 0;
pd.speed_buff = 0;
pd.terastype = [0];
});
pokemonData = pokemonDataArray[index];
}}
>
Reset Battle Status
</button><br />
<button <button
on:click={() => { on:click={() => {
pokemonData = undefined; pokemonData = undefined;
@@ -201,7 +218,9 @@
bind:special_defense_final bind:special_defense_final
bind:speed_final bind:speed_final
bind:attackId bind:attackId
bind:attackSide
{items} {items}
{playerSide}
/> />
</div> </div>
</div> </div>

View File

@@ -3,7 +3,7 @@ export interface PokemonDBData {
name: string; name: string;
types: number[]; types: number[];
thumbnail: string; thumbnail: string;
abilities: string; abilities: Record<string, string>;
hp: number; hp: number;
attack: number; attack: number;
defense: number; defense: number;
@@ -17,7 +17,7 @@ export interface PokemonData {
name: string; name: string;
types: number[]; types: number[];
thumbnail: string; thumbnail: string;
abilities: string; abilities: Record<string, string>;
hp: number; hp: number;
attack: number; attack: number;
defense: number; defense: number;
@@ -62,4 +62,6 @@ export interface PokemonLearnsetDBData {
types: number[]; types: number[];
power: number; power: number;
category: number; category: number;
priority: number;
usage: number;
} }