Add a data generator for the completed.md checklist.

This commit is contained in:
zontreck 2025-03-26 00:20:50 -07:00
parent 18641d5606
commit cef613c265
11 changed files with 1047 additions and 446 deletions

395
COMPLETED.md Normal file
View file

@ -0,0 +1,395 @@
# Generation One
- [x] Bulbasaur
- [x] Ivysaur
- [x] Venusaur
- [ ] Charmander
- [ ] Charmeleon
- [ ] Charizard
- [ ] Squirtle
- [ ] Wartortle
- [ ] Blastoise
- [x] Caterpie
- [ ] Metapod
- [ ] Butterfree
- [ ] Weedle
- [ ] Kakuna
- [ ] Beedrill
- [ ] Pidgey
- [ ] Pidgeotto
- [ ] Pidgeot
- [ ] Rattata
- [ ] Raticate
- [ ] Spearow
- [ ] Fearow
- [ ] Ekans
- [ ] Arbok
- [ ] Pikachu
- [ ] Raichu
- [ ] Sandshrew
- [ ] Sandslash
- [ ] NidoranF
- [ ] Nidorina
- [ ] NidoQueen
- [ ] NidoranM
- [ ] Nidorino
- [ ] NidoKing
- [ ] Clefairy
- [ ] Clefable
- [ ] Vulpix
- [ ] NineTales
- [ ] Jigglypuff
- [ ] WigglyTuff
- [ ] Zubat
- [ ] Golbat
- [ ] Oddish
- [ ] Gloom
- [ ] Vileplume
- [ ] Paras
- [ ] Parasect
- [ ] Venonat
- [ ] Venomoth
- [ ] Diglett
- [ ] Dugtrio
- [ ] Meowth
- [ ] Persian
- [ ] Psyduck
- [ ] Golduck
- [ ] Mankey
- [ ] Primeape
- [ ] Growlithe
- [ ] Arcanine
- [ ] Poliwag
- [ ] Poliwhirl
- [ ] Poliwrath
- [ ] Abra
- [ ] Kadabra
- [ ] Alakazam
- [ ] Machop
- [ ] Machoke
- [ ] Machamp
- [ ] Bellsprout
- [ ] Weepinbell
- [ ] Victreebel
- [ ] Tentacool
- [ ] Tentacruel
- [ ] Geodude
- [ ] Graveler
- [ ] Golem
- [ ] Ponyta
- [ ] Rapidash
- [ ] Slowpoke
- [ ] Slowbro
- [ ] Magnemite
- [ ] Magneton
- [ ] Farfetch'd
- [ ] Doduo
- [ ] Dodrio
- [ ] Seel
- [ ] Dewgong
- [ ] Grimer
- [ ] Muk
- [ ] Shellder
- [ ] Cloyster
- [ ] Gastly
- [ ] Haunter
- [ ] Gengar
- [ ] Onix
- [ ] Drowzee
- [ ] Hypno
- [ ] Krabby
- [ ] Kingler
- [ ] Voltorb
- [ ] Electrode
- [ ] Exeggcute
- [ ] Exeggutor
- [ ] Cubone
- [ ] Marowak
- [ ] Hitmonlee
- [ ] Hitmonchan
- [ ] Lickitung
- [ ] Koffing
- [ ] Weezing
- [ ] Rhyhorn
- [ ] Rhydon
- [ ] Chansey
- [ ] Tangela
- [ ] Kangaskhan
- [ ] Horsea
- [ ] Seadra
- [ ] Goldeen
- [ ] Seaking
- [ ] Staryu
- [ ] Starmie
- [ ] Mr. Mime
- [ ] Scyther
- [ ] Jynx
- [ ] Electabuzz
- [ ] Magmar
- [ ] Pinsir
- [ ] Tauros
- [ ] Magikarp
- [ ] Gyarados
- [ ] Lapras
- [ ] Ditto
- [ ] Eevee
- [ ] Vaporeon
- [ ] Jolteon
- [ ] Flareon
- [ ] Porygon
- [ ] Omanyte
- [ ] Omastar
- [ ] Kabuto
- [ ] Kabutops
- [ ] Aerodactyl
- [ ] Snorlax
- [ ] Articuno
- [ ] Zapdos
- [ ] Moltres
- [ ] Dratini
- [ ] Dragonair
- [ ] Dragonite
- [ ] Mewtwo
- [ ] Mew
# Generation Two
- [ ] Chikorita
- [ ] Bayleef
- [ ] Meganium
- [ ] Cyndaquil
- [ ] Quilava
- [ ] Typhlosion
- [ ] Totodile
- [ ] Croconaw
- [ ] Feraligatr
- [ ] Sentret
- [ ] Furret
- [ ] Hoothoot
- [ ] Noctowl
- [ ] Ledyba
- [ ] Ledian
- [ ] Spinarak
- [ ] Ariados
- [ ] Crobat
- [ ] Chinchou
- [ ] Lanturn
- [ ] Pichu
- [ ] Cleffa
- [ ] Igglybuff
- [ ] Togepi
- [ ] Togetic
- [ ] Natu
- [ ] Xatu
- [ ] Mareep
- [ ] Flaaffy
- [ ] Ampharos
- [ ] Bellossom
- [ ] Marill
- [ ] Azumarill
- [ ] Sudowoodo
- [ ] Politoed
- [ ] Hoppip
- [ ] Skiploom
- [ ] Jumpluff
- [ ] Aipom
- [ ] Sunkern
- [ ] Sunflora
- [ ] Yanma
- [ ] Wooper
- [ ] Quagsire
- [ ] Espeon
- [ ] Umbreon
- [ ] Murkrow
- [ ] Slowking
- [ ] Misdreavus
- [ ] Unown
- [ ] Wobbuffet
- [ ] Girafarig
- [ ] Pineco
- [ ] Forretress
- [ ] Dunsparce
- [ ] Gligar
- [ ] Steelix
- [ ] Snubbull
- [ ] Granbull
- [ ] Qwilfish
- [ ] Scizor
- [ ] Shuckle
- [ ] Heracross
- [ ] Sneasel
- [ ] Teddiursa
- [ ] Ursaring
- [ ] Slugma
- [ ] Magcargo
- [ ] Swinub
- [ ] Piloswine
- [ ] Corsola
- [ ] Remoraid
- [ ] Octillery
- [ ] Delibird
- [ ] Mantine
- [ ] Skarmory
- [ ] Houndour
- [ ] Houndoom
- [ ] Kingdra
- [ ] Phanpy
- [ ] Donphan
- [ ] Porygon2
- [ ] Stantler
- [ ] Smeargle
- [ ] Tyrogue
- [ ] Hitmontop
- [ ] Smoochum
- [ ] Elekid
- [ ] Magby
- [ ] Miltank
- [ ] Blissey
- [ ] Raikou
- [ ] Entei
- [ ] Suicune
- [ ] Larvitar
- [ ] Pupitar
- [ ] Tyranitar
- [ ] Lugia
- [ ] Ho-Oh
- [ ] Celebi
# Generation Three
- [ ] Treecko
- [ ] Grovyle
- [ ] Sceptile
- [ ] Torchic
- [ ] Combusken
- [ ] Blaziken
- [ ] Mudkip
- [ ] Marshtomp
- [ ] Swampert
- [ ] Poochyena
- [ ] Mightyena
- [ ] Zigzagoon
- [ ] Linoone
- [ ] Wurmple
- [ ] Silcoon
- [ ] Beautifly
- [ ] Cascoon
- [ ] Dustox
- [ ] Lotad
- [ ] Lombre
- [ ] Ludicolo
- [ ] Seedot
- [ ] Nuzleaf
- [ ] Shiftry
- [ ] Taillow
- [ ] Swellow
- [ ] Wingull
- [ ] Pelipper
- [ ] Ralts
- [ ] Kirlia
- [ ] Gardevoir
- [ ] Surskit
- [ ] Masquerain
- [ ] Shroomish
- [ ] Breloom
- [ ] Slakoth
- [ ] Vigoroth
- [ ] Slaking
- [ ] Nincada
- [ ] Ninjask
- [ ] Shedinja
- [ ] Whismur
- [ ] Loudred
- [ ] Exploud
- [ ] Makuhita
- [ ] Hariyama
- [ ] Azurill
- [ ] Nosepass
- [ ] Skitty
- [ ] Delcatty
- [ ] Sableye
- [ ] Mawile
- [ ] Aron
- [ ] Lairon
- [ ] Aggron
- [ ] Meditite
- [ ] Medicham
- [ ] Electrike
- [ ] Manectric
- [ ] Plusle
- [ ] Minun
- [ ] Volbeat
- [ ] Illumise
- [ ] Roselia
- [ ] Gulpin
- [ ] Swalot
- [ ] Carvanha
- [ ] Sharpedo
- [ ] Wailmer
- [ ] Wailord
- [ ] Numel
- [ ] Camerupt
- [ ] Torkoal
- [ ] Spoink
- [ ] Grumpig
- [ ] Spinda
- [ ] Trapinch
- [ ] Vibrava
- [ ] Flygon
- [ ] Cacnea
- [ ] Cacturne
- [ ] Swablu
- [ ] Altaria
- [ ] Zangoose
- [ ] Seviper
- [ ] Lunatone
- [ ] Solrock
- [ ] Barboach
- [ ] Whiscash
- [ ] Corphish
- [ ] Crawdaunt
- [ ] Baltoy
- [ ] Claydol
- [ ] Lileep
- [ ] Cradily
- [ ] Anorith
- [ ] Armaldo
- [ ] Feebas
- [ ] Milotic
- [ ] Castform
- [ ] Kecleon
- [ ] Shuppet
- [ ] Banette
- [ ] Duskull
- [ ] Dusclops
- [ ] Tropius
- [ ] Chimecho
- [ ] Absol
- [ ] Wynaut
- [ ] Snorunt
- [ ] Glalie
- [ ] Spheal
- [ ] Sealeo
- [ ] Walrein
- [ ] Clamperl
- [ ] Huntail
- [ ] Gorebyss
- [ ] Relicanth
- [ ] Luvdisc
- [ ] Bagon
- [ ] Shelgon
- [ ] Salamence
- [ ] Beldum
- [ ] Metang
- [ ] Metagross
- [ ] Regirock
- [ ] Regice
- [ ] Registeel
- [ ] Latias
- [ ] Latios
- [ ] Kyogre
- [ ] Groudon
- [ ] Rayquaza
- [ ] Jirachi
- [ ] Deoxys

41
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,41 @@
# Ways to Contribute
So you want to contribute to my neat little PokeDex? Awesome.
Here is what we need.
1. More pokemon sprites and dex entries.
2. Location information
3. Description data.
## More Sprites and Entries
If you look in `lib/pokemon.dart` you'll see where all the Pokemon are registered at. Simply download the sprites from a site like https://pokemondb.net/sprites
I have been using the HQ-3D sprite from Gen 8.
Currently these are the completed Generations.
- [x] Generation 1
- [x] Generation 2
- [x] Generation 3
- [ ] Generation 4
- [ ] Generation 5
- [ ] Generation 6
- [ ] Generation 7
- [ ] Generation 8
- [ ] Generation 9
## Location Information
Among other things, acquiring and merging in location information is extremely helpful.
This is added to the pokemon entry in the PokeDex as a optional parameter list.
## Descriptions
Descriptions are another piece of information that is lacking. See the COMPLETED.md file for info on which Pokemon have completed information (UP TO THE CURRENT GENERATION)
## State
At this stage, while i won't stop you from contributing it, I am only adding, myself, the location and description information for the generation we have completed. So, as of writing this, we've completed Generation 3. So location and descriptions from 1-3 is what is being added by myself. Upon completion of Gen 4, i plan to go back and add in all of those entries.

View file

@ -1,7 +1,7 @@
import 'dart:io';
class Constants {
static const VERSION = "1.0.032525+2222";
static const VERSION = "1.0.032625+0019";
//static bool get isMobile => Platform.isAndroid || Platform.isIOS;
}

View file

@ -4,6 +4,7 @@ import 'package:pokedex/Consts.dart';
import 'package:pokedex/Session.dart';
import 'package:pokedex/filters.dart';
import 'package:pokedex/pokemon.dart';
import 'package:pokedex/pokemonHelpers.dart';
class MainApp extends StatefulWidget {
const MainApp({super.key});
@ -182,7 +183,7 @@ class _DexEntryState extends State<DexEntry> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Type: ", style: TextStyle(fontSize: 24)),
_pkmn.getTypeWidgets(),
PokemonHelpers.getTypeWidgets(_pkmn),
],
),
Row(
@ -196,26 +197,28 @@ class _DexEntryState extends State<DexEntry> {
),
if (_pkmn.extraVariants.isNotEmpty)
Text("Extra Variations: ", style: TextStyle(fontSize: 24)),
if (_pkmn.extraVariants.isNotEmpty) _pkmn.getVariations(),
if (_pkmn.extraVariants.isNotEmpty)
PokemonHelpers.getVariations(_pkmn),
SizedBox(height: 32),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: _pkmn.getEvolutions(0),
children: PokemonHelpers.getEvolutions(0, _pkmn),
),
),
if (SessionData.enableDescription && _pkmn.dexEntries.isNotEmpty)
Text("Description: ", style: TextStyle(fontSize: 24)),
if (SessionData.enableDescription && _pkmn.dexEntries.isNotEmpty)
_pkmn.printDescription(),
PokemonHelpers.printDescription(_pkmn),
SizedBox(height: 50),
if (_pkmn.locations.isNotEmpty)
Text("Where to find:", style: TextStyle(fontSize: 24)),
if (_pkmn.locations.isNotEmpty) _pkmn.printLocations(),
if (_pkmn.locations.isNotEmpty)
PokemonHelpers.printLocations(_pkmn),
],
),
),

View file

@ -1,8 +1,5 @@
import 'dart:math';
import 'package:flutter/widgets.dart';
import 'package:pokedex/Consts.dart';
import 'package:pokedex/filters.dart';
import 'package:pokedex/pokemon.dart';
class SessionData {
@ -54,43 +51,6 @@ class SessionData {
return "assets/sprites/unown-${digit.toLowerCase()}.png";
}
static Widget PrintUnown() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: getUnownList(),
);
}
static List<Widget> getUnownList() {
List<Widget> widgets = [];
List<Widget> tmpWidgets = [];
int i = 0;
int end = 3;
for (var digit in ALPHABET) {
tmpWidgets.add(
Image.asset("assets/sprites/unown-${digit.toLowerCase()}.png"),
);
i++;
if (i >= end) {
widgets.add(
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: tmpWidgets,
),
);
i = 0;
tmpWidgets = [];
}
}
widgets.add(
Row(crossAxisAlignment: CrossAxisAlignment.start, children: tmpWidgets),
);
return widgets;
}
static int highestGenID() {
if (_lastMaxID != Pokemon.values.length) resetHighestGenCache();
if (_cachedHighest != -1) return _cachedHighest;

View file

@ -42,7 +42,8 @@ enum GameRoute {
// The following mark the pokemon as not usually obtainable
TradeOrMigrate(commonName: "Trade or Migrate from another game"),
BreedOnly(commonName: "Only obtainable via breeding"),
Evolve(commonName: "Evolve another pokemon");
Evolve(commonName: "Evolve another pokemon"),
Unavailable;
final String commonName;
const GameRoute({this.commonName = ""});

View file

@ -1,9 +1,9 @@
// ignore_for_file: constant_identifier_names
import 'package:flutter/material.dart';
import 'package:pokedex/Consts.dart';
import 'package:pokedex/Session.dart';
import 'package:pokedex/dexMisc.dart';
import 'package:pokedex/pokemonHelpers.dart';
enum Generation {
One(1, 151),
@ -20,54 +20,6 @@ enum Generation {
final int idEnd;
const Generation(this.idStart, this.idEnd);
toSpritePath() {
switch (this) {
case Generation.One:
return 'assets/sprites/gen1';
case Generation.Two:
return 'assets/sprites/gen2';
case Generation.Three:
return 'assets/sprites/gen3';
case Generation.Four:
return 'assets/sprites/gen4';
case Generation.Five:
return 'assets/sprites/gen5';
case Generation.Six:
return 'assets/sprites/gen6';
case Generation.Seven:
return 'assets/sprites/gen7';
case Generation.Eight:
return 'assets/sprites/gen8';
case Generation.Nine:
return 'assets/sprites/gen9';
}
}
}
enum Type {
Normal(Color.fromARGB(255, 192, 192, 192), Colors.black),
Fire(Color.fromARGB(255, 255, 0, 0), Color.fromARGB(255, 255, 255, 255)),
Water(Color.fromARGB(255, 0, 174, 255), Colors.black),
Electric(Color(0xffFFD700), Colors.black),
Grass(Color.fromARGB(255, 0, 255, 0), Colors.black),
Ice(Color.fromARGB(255, 0, 255, 255), Colors.black),
Fighting(Color.fromARGB(255, 255, 0, 0), Color.fromARGB(255, 255, 255, 255)),
Poison(Color.fromARGB(255, 128, 0, 128), Color.fromARGB(255, 255, 255, 255)),
Ground(Color.fromARGB(255, 128, 126, 0), Colors.black),
Flying(Color.fromARGB(255, 128, 128, 255), Colors.black),
Psychic(Color.fromARGB(255, 255, 0, 255), Color.fromARGB(255, 255, 255, 255)),
Bug(Color.fromARGB(255, 128, 128, 0), Colors.black),
Rock(Color.fromARGB(255, 128, 128, 128), Colors.black),
Ghost(Color.fromARGB(255, 128, 0, 128), Colors.black),
Dragon(Color.fromARGB(255, 85, 0, 102), Color.fromARGB(255, 255, 255, 255)),
Dark(Color.fromARGB(255, 51, 51, 51), Color.fromARGB(255, 255, 255, 255)),
Steel(Color.fromARGB(255, 192, 192, 192), Colors.black),
Fairy(Color.fromARGB(255, 255, 102, 255), Colors.black);
final Color backgroundColor;
final Color textColor;
const Type(this.backgroundColor, this.textColor);
}
enum EvolutionCondition {
@ -106,160 +58,6 @@ enum EvolutionCondition {
DeepSeaScale,
}
abstract class Evolution {
const Evolution();
String printEvolution();
Widget getEvolution();
}
class SingleEvolution extends Evolution {
final int to;
final int level;
final List<EvolutionCondition>? condition;
const SingleEvolution(this.to, this.level, {this.condition});
@override
String printEvolution() {
String sRet = "";
if (level != -1) {
sRet += "Level $level";
}
if (condition != null) {
if (sRet.isNotEmpty) {
sRet += "\n";
}
for (var cond in condition!) {
sRet += cond.name;
}
}
return sRet;
}
@override
Widget getEvolution() {
if (to >= SessionData.highestGenID() + 1) {
return Column();
}
Pokemon pkmn = Pokemon.values.where((x) => x.id == to).first;
List<Widget> cardRow = [];
cardRow.add(
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.arrow_downward, size: 48),
Card(
elevation: 50,
child: SizedBox(
width: 256,
height: 256,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(printEvolution(), style: TextStyle(fontSize: 16)),
Image.asset(pkmn.toDexPath(), width: 64, height: 64),
Text(pkmn.pokemonName, style: TextStyle(fontSize: 24)),
pkmn.getTypeWidgets(),
],
),
),
),
],
),
);
Column rw = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Row(children: cardRow)],
);
return rw;
}
}
class BranchedEvolution extends Evolution {
final List<int> alternates;
final List<int> levels;
final List<List<EvolutionCondition>> conditions;
const BranchedEvolution(this.alternates, this.levels, this.conditions);
@override
String printEvolution() {
return "";
}
String _prntEV(List<EvolutionCondition> conds, int level) {
String sRet = "";
if (level != -1) {
sRet += "Level ${level}";
}
for (var condition in conds) {
sRet += condition.name + " ";
}
return sRet;
}
@override
Widget getEvolution() {
// This is a branched evolution. So first, we print the arrows, and conditions.
List<Widget> cardRow = [];
for (var pkmn in alternates) {
int index = alternates.indexOf(pkmn);
if (pkmn >= SessionData.highestGenID() + 1) {
print("Index too high");
continue;
}
Pokemon _pkmn = Pokemon.values.where((x) => x.id == pkmn).first;
cardRow.add(
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.arrow_downward, size: 48),
Card(
elevation: 50,
child: SizedBox(
width: 256,
height: 256,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
_prntEV(conditions[index], levels[index]),
style: TextStyle(fontSize: 16),
),
Image.asset(_pkmn.toDexPath(), width: 64, height: 64),
Text(_pkmn.pokemonName, style: TextStyle(fontSize: 24)),
_pkmn.getTypeWidgets(),
],
),
),
),
],
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Row(children: cardRow)],
);
}
}
enum LearnType { TM, HM }
enum Move {
@ -2122,24 +1920,6 @@ enum Pokemon {
return 'assets/sprites/${printName().replaceAll("", "-f").replaceAll("", "-m").toLowerCase()}.png';
}
Widget getTypeWidgets() {
List<Widget> widgets = [];
for (Type type in types) {
widgets.add(
ElevatedButton(
onPressed: () {},
style: ButtonStyle(
backgroundColor: WidgetStatePropertyAll(type.backgroundColor),
foregroundColor: WidgetStatePropertyAll(type.textColor),
),
child: Text(type.name, style: TextStyle(fontSize: 16)),
),
);
}
return Row(children: widgets);
}
String printName({var proper = false}) {
String sRet;
@ -2154,181 +1934,4 @@ enum Pokemon {
return sRet;
}
Widget getVariations() {
List<Widget> variants = [];
if (id == Pokemon.Unown.id)
variants = SessionData.getUnownList();
else {
List<Widget> tmpRow = [];
int i = 0;
int row = 3;
for (var variant in extraVariants) {
tmpRow.add(Image.asset("assets/sprites/${variant}.png"));
i++;
if (i >= row) {
variants.add(Row(children: tmpRow));
tmpRow = [];
i = 0;
}
}
if (tmpRow.isNotEmpty) variants.add(Row(children: tmpRow));
}
return Column(children: variants);
}
List<Widget> getEvolutions(int subID) {
//print("SUBID ${subID}");
List<Pokemon> Evs = [];
// ID must be in inclusive range of 1...MAXGeneration
if (previousPokemon != -1 &&
previousPokemon <= SessionData.highestGenID()) {
if (previousPokemon != -1 && subID == 0) {
Pokemon pkmn =
Pokemon.values.where((x) => x.id == previousPokemon).first;
return pkmn.getEvolutions(0);
}
}
if (!hasEvolutions) return [];
//print("Processing evolutions for ${pokemonName}");
if (evolution is SingleEvolution) {
//print("Single Evolution identified");
var pokemon =
Pokemon.values
.where((x) => x.id == (evolution! as SingleEvolution).to)
.first;
if (pokemon.id <= SessionData.highestGenID()) Evs.add(pokemon);
} else {
//print("Branching Evolution identified");
// Handle branched evolutions. Refactor below to accomodate a list of pokemon.
for (var ev in (evolution! as BranchedEvolution).alternates) {
if (!(ev >= SessionData.highestGenID())) {
var pokemon = Pokemon.values.where((x) => x.id == ev).first;
if (pokemon.id <= SessionData.highestGenID()) Evs.add(pokemon);
}
}
}
List<Widget> sprites = [];
if (subID == 0) {
sprites.add(Text("Evolutions: ", style: TextStyle(fontSize: 24)));
sprites.add(
Card(
elevation: 50,
child: SizedBox(
width: 256,
height: 256,
child: Column(
children: [
Image.asset(toDexPath(), width: 64, height: 64),
Text(pokemonName, style: TextStyle(fontSize: 24)),
getTypeWidgets(),
],
),
),
),
);
sprites.add(evolution!.getEvolution());
//print("Main page EV.");
} else {
sprites.add(evolution!.getEvolution());
}
List<Widget> afterEvs = [];
for (var ev in Evs) {
afterEvs.addAll(ev.getEvolutions(subID + 1));
//print("Processing evolution: ${ev.properName}");
}
sprites.add(
Row(crossAxisAlignment: CrossAxisAlignment.start, children: afterEvs),
);
return sprites;
}
Widget printDescription() {
List<Widget> widgets = [];
for (var descs in dexEntries) {
if (descs.gameGen.idStart > SessionData.highestGenID()) continue;
List<String> gameNames = [descs.game.toString()];
for (var extra in descs.additionalGames) {
gameNames.add(extra.toString());
}
widgets.add(
Card.filled(
elevation: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
"Game: ${gameNames.join(", ")}\nDescription: ${descs.desc}",
),
],
),
),
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: widgets,
);
}
Widget printLocations() {
List<Widget> widgets = [];
for (var locs in locations) {
if (locs.gameGen.idStart > SessionData.highestGenID()) continue;
List<String> routes = [];
for (var rt in locs.routes) {
routes.add(rt.toString());
}
List<String> gameNames = [locs.game.toString()];
for (var extra in locs.additionalGames) {
gameNames.add(extra.toString());
}
widgets.add(
Card.outlined(
elevation: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
"Game: ${gameNames.join(", ")}\n\nRoutes/Method: ${routes.join(", ")}",
),
],
),
),
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: widgets,
);
}
}

410
lib/pokemonHelpers.dart Normal file
View file

@ -0,0 +1,410 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:pokedex/Session.dart';
import 'package:pokedex/pokemon.dart';
enum Type {
Normal(Color.fromARGB(255, 192, 192, 192), Colors.black),
Fire(Color.fromARGB(255, 255, 0, 0), Color.fromARGB(255, 255, 255, 255)),
Water(Color.fromARGB(255, 0, 174, 255), Colors.black),
Electric(Color(0xffFFD700), Colors.black),
Grass(Color.fromARGB(255, 0, 255, 0), Colors.black),
Ice(Color.fromARGB(255, 0, 255, 255), Colors.black),
Fighting(Color.fromARGB(255, 255, 0, 0), Color.fromARGB(255, 255, 255, 255)),
Poison(Color.fromARGB(255, 128, 0, 128), Color.fromARGB(255, 255, 255, 255)),
Ground(Color.fromARGB(255, 128, 126, 0), Colors.black),
Flying(Color.fromARGB(255, 128, 128, 255), Colors.black),
Psychic(Color.fromARGB(255, 255, 0, 255), Color.fromARGB(255, 255, 255, 255)),
Bug(Color.fromARGB(255, 128, 128, 0), Colors.black),
Rock(Color.fromARGB(255, 128, 128, 128), Colors.black),
Ghost(Color.fromARGB(255, 128, 0, 128), Colors.black),
Dragon(Color.fromARGB(255, 85, 0, 102), Color.fromARGB(255, 255, 255, 255)),
Dark(Color.fromARGB(255, 51, 51, 51), Color.fromARGB(255, 255, 255, 255)),
Steel(Color.fromARGB(255, 192, 192, 192), Colors.black),
Fairy(Color.fromARGB(255, 255, 102, 255), Colors.black);
final Color backgroundColor;
final Color textColor;
const Type(this.backgroundColor, this.textColor);
}
class PokemonHelpers {
static List<Widget> getUnownList() {
List<Widget> widgets = [];
List<Widget> tmpWidgets = [];
int i = 0;
int end = 3;
for (var digit in SessionData.ALPHABET) {
tmpWidgets.add(
Image.asset("assets/sprites/unown-${digit.toLowerCase()}.png"),
);
i++;
if (i >= end) {
widgets.add(
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: tmpWidgets,
),
);
i = 0;
tmpWidgets = [];
}
}
widgets.add(
Row(crossAxisAlignment: CrossAxisAlignment.start, children: tmpWidgets),
);
return widgets;
}
static Widget getTypeWidgets(Pokemon pokemon) {
List<Widget> widgets = [];
for (Type type in pokemon.types) {
widgets.add(
ElevatedButton(
onPressed: () {},
style: ButtonStyle(
backgroundColor: WidgetStatePropertyAll(type.backgroundColor),
foregroundColor: WidgetStatePropertyAll(type.textColor),
),
child: Text(type.name, style: TextStyle(fontSize: 16)),
),
);
}
return Row(children: widgets);
}
static Widget getVariations(Pokemon pokemon) {
List<Widget> variants = [];
if (pokemon.id == Pokemon.Unown.id) {
variants = getUnownList();
} else {
List<Widget> tmpRow = [];
int i = 0;
int row = 3;
for (var variant in pokemon.extraVariants) {
tmpRow.add(Image.asset("assets/sprites/${variant}.png"));
i++;
if (i >= row) {
variants.add(Row(children: tmpRow));
tmpRow = [];
i = 0;
}
}
if (tmpRow.isNotEmpty) variants.add(Row(children: tmpRow));
}
return Column(children: variants);
}
static List<Widget> getEvolutions(int subID, Pokemon pokemon) {
//print("SUBID ${subID}");
List<Pokemon> Evs = [];
// ID must be in inclusive range of 1...MAXGeneration
if (pokemon.previousPokemon != -1 &&
pokemon.previousPokemon <= SessionData.highestGenID()) {
if (pokemon.previousPokemon != -1 && subID == 0) {
Pokemon pkmn =
Pokemon.values.where((x) => x.id == pokemon.previousPokemon).first;
return getEvolutions(0, pkmn);
}
}
if (!pokemon.hasEvolutions) return [];
//print("Processing evolutions for ${pokemonName}");
if (pokemon.evolution is SingleEvolution) {
//print("Single Evolution identified");
var pkmnx =
Pokemon.values
.where((x) => x.id == (pokemon.evolution! as SingleEvolution).to)
.first;
if (pkmnx.id <= SessionData.highestGenID()) Evs.add(pkmnx);
} else {
//print("Branching Evolution identified");
// Handle branched evolutions. Refactor below to accomodate a list of pokemon.
for (var ev in (pokemon.evolution! as BranchedEvolution).alternates) {
if (!(ev >= SessionData.highestGenID())) {
var pkmnx = Pokemon.values.where((x) => x.id == ev).first;
if (pkmnx.id <= SessionData.highestGenID()) Evs.add(pkmnx);
}
}
}
List<Widget> sprites = [];
if (subID == 0) {
sprites.add(Text("Evolutions: ", style: TextStyle(fontSize: 24)));
sprites.add(
Card(
elevation: 50,
child: SizedBox(
width: 256,
height: 256,
child: Column(
children: [
Image.asset(pokemon.toDexPath(), width: 64, height: 64),
Text(pokemon.pokemonName, style: TextStyle(fontSize: 24)),
getTypeWidgets(pokemon),
],
),
),
),
);
sprites.add(pokemon.evolution!.getEvolution());
//print("Main page EV.");
} else {
sprites.add(pokemon.evolution!.getEvolution());
}
List<Widget> afterEvs = [];
for (var ev in Evs) {
afterEvs.addAll(getEvolutions(subID + 1, ev));
//print("Processing evolution: ${ev.properName}");
}
sprites.add(
Row(crossAxisAlignment: CrossAxisAlignment.start, children: afterEvs),
);
return sprites;
}
static Widget printDescription(Pokemon pokemon) {
List<Widget> widgets = [];
for (var descs in pokemon.dexEntries) {
if (descs.gameGen.idStart > SessionData.highestGenID()) continue;
List<String> gameNames = [descs.game.toString()];
for (var extra in descs.additionalGames) {
gameNames.add(extra.toString());
}
widgets.add(
Card.filled(
elevation: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
"Game: ${gameNames.join(", ")}\nDescription: ${descs.desc}",
),
],
),
),
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: widgets,
);
}
static Widget printLocations(Pokemon pokemon) {
List<Widget> widgets = [];
for (var locs in pokemon.locations) {
if (locs.gameGen.idStart > SessionData.highestGenID()) continue;
List<String> routes = [];
for (var rt in locs.routes) {
routes.add(rt.toString());
}
List<String> gameNames = [locs.game.toString()];
for (var extra in locs.additionalGames) {
gameNames.add(extra.toString());
}
widgets.add(
Card.outlined(
elevation: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
"Game: ${gameNames.join(", ")}\n\nRoutes/Method: ${routes.join(", ")}",
),
],
),
),
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: widgets,
);
}
}
abstract class Evolution {
const Evolution();
String printEvolution();
Widget getEvolution();
}
class SingleEvolution extends Evolution {
final int to;
final int level;
final List<EvolutionCondition>? condition;
const SingleEvolution(this.to, this.level, {this.condition});
@override
String printEvolution() {
String sRet = "";
if (level != -1) {
sRet += "Level $level";
}
if (condition != null) {
if (sRet.isNotEmpty) {
sRet += "\n";
}
for (var cond in condition!) {
sRet += cond.name;
}
}
return sRet;
}
@override
Widget getEvolution() {
if (to >= SessionData.highestGenID() + 1) {
return Column();
}
Pokemon pkmn = Pokemon.values.where((x) => x.id == to).first;
List<Widget> cardRow = [];
cardRow.add(
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.arrow_downward, size: 48),
Card(
elevation: 50,
child: SizedBox(
width: 256,
height: 256,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(printEvolution(), style: TextStyle(fontSize: 16)),
Image.asset(pkmn.toDexPath(), width: 64, height: 64),
Text(pkmn.pokemonName, style: TextStyle(fontSize: 24)),
PokemonHelpers.getTypeWidgets(pkmn),
],
),
),
),
],
),
);
Column rw = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Row(children: cardRow)],
);
return rw;
}
}
class BranchedEvolution extends Evolution {
final List<int> alternates;
final List<int> levels;
final List<List<EvolutionCondition>> conditions;
const BranchedEvolution(this.alternates, this.levels, this.conditions);
@override
String printEvolution() {
return "";
}
String _prntEV(List<EvolutionCondition> conds, int level) {
String sRet = "";
if (level != -1) {
sRet += "Level ${level}";
}
for (var condition in conds) {
sRet += condition.name + " ";
}
return sRet;
}
@override
Widget getEvolution() {
// This is a branched evolution. So first, we print the arrows, and conditions.
List<Widget> cardRow = [];
for (var pkmn in alternates) {
int index = alternates.indexOf(pkmn);
if (pkmn >= SessionData.highestGenID() + 1) {
print("Index too high");
continue;
}
Pokemon _pkmn = Pokemon.values.where((x) => x.id == pkmn).first;
cardRow.add(
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.arrow_downward, size: 48),
Card(
elevation: 50,
child: SizedBox(
width: 256,
height: 256,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
_prntEV(conditions[index], levels[index]),
style: TextStyle(fontSize: 16),
),
Image.asset(_pkmn.toDexPath(), width: 64, height: 64),
Text(_pkmn.pokemonName, style: TextStyle(fontSize: 24)),
PokemonHelpers.getTypeWidgets(_pkmn),
],
),
),
),
],
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Row(children: cardRow)],
);
}
}

184
lib/updateTool.dart Normal file
View file

@ -0,0 +1,184 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:libac_dart/nbt/Stream.dart';
import 'package:libacflutter/Constants.dart';
import 'package:pokedex/Session.dart';
import 'package:pokedex/pokemon.dart';
Future<int> main(List<String> args) async {
runApp(CompletedGenerator());
return 0;
}
class CompletedGenerator extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _completedGen();
}
}
class _completedGen extends State<CompletedGenerator> {
@override
Widget build(BuildContext context) {
return MaterialApp(theme: ThemeData.dark(), home: MainGen());
}
}
class MainGen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _main();
}
}
class _main extends State<MainGen> {
bool firstLaunch = true;
double progress = 0;
String statusMessage = "";
Generation gen = Generation.One;
StringBuilder sb = StringBuilder();
int index = 0;
Generation? currentGen = null;
int maxTasks = 5;
int state = 0;
@override
void didChangeDependencies() {
if (firstLaunch) {
firstLaunch = false;
setState(() {
statusMessage = "Warming up...";
progress = 0.0;
});
Timer.periodic(Duration(milliseconds: 100), (x) async {
if (state == 0) {
sleep(Duration(seconds: 5));
statusMessage = "Acquiring game generation";
progress = 0.25;
setState(() {});
state++;
} else if (state == 1) {
SessionData.resetHighestGenCache();
int highest = SessionData.highestGenID();
// Get actual generation
gen = Generation.One;
for (var _gen in Generation.values) {
if (_gen.idStart < highest) {
gen = _gen;
}
}
statusMessage = "Generation acquired";
progress = 1.0;
state++;
setState(() {});
} else if (state == 2) {
statusMessage = "Generation ${gen.name}";
progress = 0.0;
state++;
setState(() {});
} else if (state == 3) {
statusMessage = "Analyzing Pokemon...";
index = 0;
currentGen = null;
state++;
setState(() {});
} else if (state == 4) {
maxTasks += Pokemon.values.length;
state++;
setState(() {});
} else if ((state - index) == 5) {
// Pokemon iteration task
int iterNumber = state - 5;
if (iterNumber >= Pokemon.values.length) {
state++;
setState(() {});
return;
}
var pokemon = Pokemon.values[iterNumber];
if (currentGen != pokemon.generation) {
sb.append("\n# Generation ${pokemon.generation.name}\n\n");
currentGen = pokemon.generation;
}
progress = index * 100 / Pokemon.values.length;
statusMessage =
("- Analysis of pokemon ${pokemon.pokemonName} has begun");
// TODO : This needs to check locations and dex entries to see if they are up to date with the latest generation.
// The future task should take into account the generation the pokemon was introduced in. (EX. If introduced in gen 2, it won't have data entries for gen 1).
if (pokemon.locations.isEmpty && pokemon.dexEntries.isEmpty) {
sb.append("- [ ] ${pokemon.pokemonName}\n");
} else {
if (pokemon.locations.isNotEmpty && pokemon.dexEntries.isNotEmpty) {
sb.append("- [x] ${pokemon.pokemonName}\n");
} else if (pokemon.locations.isNotEmpty) {
sb.append("- [ ] ${pokemon.pokemonName} (MISSING DEX ENTRIES)\n");
} else if (pokemon.dexEntries.isNotEmpty) {
sb.append(
"- [ ] ${pokemon.pokemonName} (MISSING LOCATION ENTRIES)\n",
);
}
}
index++;
progress = progress / 100; // push it into a 0-1 range.
state++;
setState(() {});
} else if (state - index == 6) {
// Task - write file
maxTasks += 3;
statusMessage = "Saving to COMPLETED.md";
File complete = File("COMPLETED.md");
progress = 99.75;
state++;
setState(() {});
await complete.writeAsString(sb.toString());
} else if (state - index == 7) {
statusMessage = "Data generation completed";
progress = 1.0;
state++;
setState(() {});
} else if (state - index == 8) {
x.cancel();
sleep(Duration(seconds: 10));
exit(0);
}
});
}
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Data Generator"),
backgroundColor: LibACFlutterConstants.TITLEBAR_COLOR,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Status: ${statusMessage}", style: TextStyle(fontSize: 24)),
Text("Progress: ${progress * 100}%", style: TextStyle(fontSize: 24)),
Text("Task ${state}/${maxTasks}", style: TextStyle(fontSize: 24)),
LinearProgressIndicator(value: progress, minHeight: 30),
],
),
);
}
}

View file

@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.032525+2222
version: 1.0.032625+0019
environment:
sdk: ^3.7.0

4
update_completed.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
flutter build linux -t lib/updateTool.dart
build/linux/x64/release/bundle/pokedex