diff --git a/library/Library.csproj b/library/Library.csproj
index 53f8c276..191eb6c5 100644
--- a/library/Library.csproj
+++ b/library/Library.csproj
@@ -103,6 +103,7 @@
+
diff --git a/library/Pokedex/Location.cs b/library/Pokedex/Location.cs
index 87bc1799..a7b4108d 100644
--- a/library/Pokedex/Location.cs
+++ b/library/Pokedex/Location.cs
@@ -69,22 +69,75 @@ namespace PkmnFoundations.Pokedex
public int? Value6 { get; private set; }
public int? Value(Generations generation)
+ {
+ LocationNumbering numbering = GenerationToLocationNumbering(generation);
+ return Value(numbering);
+ }
+
+ public int ? Value(LocationNumbering numbering)
+ {
+ switch (numbering)
+ {
+ case LocationNumbering.Generation1:
+ case LocationNumbering.Generation2:
+ throw new NotSupportedException();
+ case LocationNumbering.Generation3:
+ return Value3;
+ case LocationNumbering.Colosseum:
+ return ValueColo;
+ case LocationNumbering.XD:
+ return ValueXd;
+ case LocationNumbering.Generation4:
+ return Value4;
+ case LocationNumbering.Generation5:
+ return Value5;
+ case LocationNumbering.Generation6:
+ return Value6;
+ default:
+ throw new ArgumentException();
+ }
+ }
+
+ public static LocationNumbering GenerationToLocationNumbering(Generations generation)
{
switch (generation)
{
case Generations.Generation1:
+ return LocationNumbering.Generation1;
case Generations.Generation2:
- throw new NotSupportedException();
+ return LocationNumbering.Generation2;
case Generations.Generation3:
- return Value3;
+ return LocationNumbering.Generation3;
case Generations.Generation4:
- return Value4;
+ return LocationNumbering.Generation4;
case Generations.Generation5:
- return Value5;
+ return LocationNumbering.Generation5;
case Generations.Generation6:
+ return LocationNumbering.Generation6;
default:
- return Value6;
+ throw new ArgumentException();
}
}
+
+ public static LazyKeyValuePair CreatePair(Pokedex pokedex)
+ {
+ return new LazyKeyValuePair(
+ k => k == 0 ? null : (pokedex == null ? null : pokedex.Locations(k)),
+ v => v == null ? 0 : v.ID);
+ }
+
+ public static LazyKeyValuePair CreatePairForGeneration(Pokedex pokedex, Func generationGetter)
+ {
+ return new LazyKeyValuePair(
+ k => k == 0 ? null : (pokedex == null ? null : pokedex.Locations(GenerationToLocationNumbering(generationGetter()))[k]),
+ v => v == null ? 0 : (v.Value(generationGetter()) ?? -1));
+ }
+
+ public static LazyKeyValuePair CreatePairForLocationNumbering(Pokedex pokedex, Func generationGetter)
+ {
+ return new LazyKeyValuePair(
+ k => k == 0 ? null : (pokedex == null ? null : pokedex.Locations(generationGetter())[k]),
+ v => v == null ? 0 : (v.Value(generationGetter()) ?? -1));
+ }
}
}
diff --git a/library/Structures/Enums.cs b/library/Structures/Enums.cs
index 3e778668..73a96f84 100644
--- a/library/Structures/Enums.cs
+++ b/library/Structures/Enums.cs
@@ -28,13 +28,14 @@ namespace PkmnFoundations.Structures
public enum LocationNumbering
{
- Generation2 = 1,
- Generation3 = 2,
- Colosseum = 3,
- XD = 4,
- Generation4 = 5,
- Generation5 = 6,
- Generation6 = 7,
+ Generation1,
+ Generation2,
+ Generation3,
+ Colosseum,
+ XD,
+ Generation4,
+ Generation5,
+ Generation6
}
public enum Versions : byte
diff --git a/library/Structures/Pokemon4.cs b/library/Structures/Pokemon4.cs
index 12d250ca..d4f79023 100644
--- a/library/Structures/Pokemon4.cs
+++ b/library/Structures/Pokemon4.cs
@@ -264,6 +264,42 @@ namespace PkmnFoundations.Structures
public ushort LocationID_Plat { get; set; }
public byte EncounterLevel { get; set; }
+ public override TrainerMemo TrainerMemo
+ {
+ get
+ {
+ // fixme: Pal Park memos are just saying Pal Park. We should be able to get the region too.
+ ushort eggLocationId, locationId;
+ bool plat = IsPlatHgss();
+ eggLocationId = (plat && EggLocationID_Plat != 0) ? EggLocationID_Plat : EggLocationID;
+ locationId = (plat && LocationID_Plat != 0) ? LocationID_Plat : LocationID;
+
+ return new TrainerMemo(m_pokedex, LocationNumbering.Generation4,
+ TrainerMemoDateTime(EggDate), TrainerMemoDateTime(Date),
+ eggLocationId, locationId, EncounterLevel == 0, EncounterLevel);
+ }
+ set
+ {
+ base.TrainerMemo = value;
+ }
+ }
+
+ private DateTime ? TrainerMemoDateTime(byte[] data)
+ {
+ // todo: merge with GtsRecordBase datetime helper.
+ if (data.Length != 3) throw new ArgumentException();
+ if (data[1] == 0 && data[2] == 0 && data[0] == 0) return null;
+
+ try
+ {
+ return new DateTime(2000 + data[0], data[1], data[2]);
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ return null;
+ }
+ }
+
// this is the notorious genIV encounter type flag, not used for much besides validation
public byte EncounterType { get; set; }
public byte Unknown4 { get; set; } // appears just after HGSS pokeball
@@ -308,6 +344,11 @@ namespace PkmnFoundations.Structures
}
}
+ private bool IsPlatHgss()
+ {
+ return (Version == Versions.Platinum || Version == Versions.HeartGold || Version == Versions.SoulSilver);
+ }
+
private bool IsHgss()
{
return (Version == Versions.HeartGold || Version == Versions.SoulSilver);
diff --git a/library/Structures/PokemonPartyBase.cs b/library/Structures/PokemonPartyBase.cs
index ab72307c..80d2cfa3 100644
--- a/library/Structures/PokemonPartyBase.cs
+++ b/library/Structures/PokemonPartyBase.cs
@@ -144,5 +144,11 @@ namespace PkmnFoundations.Structures
byte mask = (byte)(1 << (value & 0x07));
return (ribbons[offset] & mask) != 0;
}
+
+ public virtual TrainerMemo TrainerMemo
+ {
+ get;
+ set;
+ }
}
}
diff --git a/library/Structures/TrainerMemo.cs b/library/Structures/TrainerMemo.cs
new file mode 100644
index 00000000..5694ab8c
--- /dev/null
+++ b/library/Structures/TrainerMemo.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using PkmnFoundations.Pokedex;
+using PkmnFoundations.Support;
+
+namespace PkmnFoundations.Structures
+{
+ public class TrainerMemo
+ {
+ public TrainerMemo(Pokedex.Pokedex pokedex, LocationNumbering numbering,
+ DateTime ? time_egg_obtained, DateTime ? time_encountered,
+ int location_egg_obtained_id, int location_encountered_id,
+ bool is_hatched, byte level_encountered)
+ {
+ m_pokedex = pokedex;
+ m_location_egg_obtained_pair = Location.CreatePairForLocationNumbering(m_pokedex, () => Numbering);
+ m_location_encountered_pair = Location.CreatePairForLocationNumbering(m_pokedex, () => Numbering);
+
+ Numbering = numbering;
+ TimeEggObtained = time_egg_obtained;
+ TimeEncountered = time_encountered;
+ m_location_egg_obtained_pair.Key = location_egg_obtained_id;
+ m_location_encountered_pair.Key = location_encountered_id;
+ IsHatched = is_hatched;
+ LevelEncountered = level_encountered;
+ }
+
+ private Pokedex.Pokedex m_pokedex;
+ public LocationNumbering Numbering { get; private set; }
+
+ public DateTime? TimeEggObtained { get; private set; }
+ public DateTime? TimeEncountered { get; private set; }
+
+ private LazyKeyValuePair m_location_egg_obtained_pair;
+ public int LocationEggObtainedID
+ {
+ get
+ {
+ return m_location_egg_obtained_pair.Key;
+ }
+ }
+ public Location LocationEggObtained
+ {
+ get
+ {
+ return m_location_egg_obtained_pair.Value;
+ }
+ }
+
+ private LazyKeyValuePair m_location_encountered_pair;
+ public int LocationEncounteredID
+ {
+ get
+ {
+ return m_location_encountered_pair.Key;
+ }
+ }
+ public Location LocationEncountered
+ {
+ get
+ {
+ return m_location_encountered_pair.Value;
+ }
+ }
+
+ public bool IsHatched { get; private set; }
+ public byte LevelEncountered { get; private set; }
+
+ public override String ToString()
+ {
+ if (IsHatched)
+ {
+ String timeEgg = TimeEggObtained == null ? "???" : ((DateTime)TimeEggObtained).ToString("D");
+ String timeGiven = TimeEncountered == null ? "???" : ((DateTime)TimeEncountered).ToString("D");
+ return String.Format("Egg obtained from {1} on {0:D}. Hatched in {3} on {2:D}.", timeEgg, LocationToString(LocationEggObtained, LocationEggObtainedID), timeGiven, LocationToString(LocationEncountered, LocationEncounteredID));
+ }
+ else
+ {
+ String level = LevelEncountered.ToString();
+ String time = TimeEncountered == null ? "???" : ((DateTime)TimeEncountered).ToString("D");
+ return String.Format("Met at Lv. {0} in {2} on {1:D}.", level, time, LocationToString(LocationEncountered, LocationEncounteredID));
+ }
+ }
+
+ private String LocationToString(Location l, int id)
+ {
+ if (l == null || l.Name == null) return "Mystery zone #" + id.ToString();
+ return l.Name.ToString();
+ }
+ }
+}
diff --git a/web/gts/Pokemon.aspx.cs b/web/gts/Pokemon.aspx.cs
index 13cf68c9..f9ecab56 100644
--- a/web/gts/Pokemon.aspx.cs
+++ b/web/gts/Pokemon.aspx.cs
@@ -92,6 +92,7 @@ namespace PkmnFoundations.Web.gts
imgPokeball.ToolTip = pkmn.Pokeball.Name.ToString();
litLevel.Text = pkmn.Level.ToString();
litGender.Text = WebFormat.Gender(pkmn.Gender);
+ litTrainerMemo.Text = pkmn.TrainerMemo.ToString();
litCharacteristic.Text = pkmn.Characteristic.ToString();
litSpecies.Text = pkmn.Species.Name.ToString();
litPokedex.Text = pkmn.SpeciesID.ToString("000");