Skip to content

Commit

Permalink
proper empire parsing/extracting
Browse files Browse the repository at this point in the history
  • Loading branch information
alaingilbert committed Aug 13, 2021
1 parent 393f294 commit 9634fef
Show file tree
Hide file tree
Showing 9 changed files with 775 additions and 1 deletion.
17 changes: 17 additions & 0 deletions empireCelestial.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ogame

// EmpireCelestial celestial information extracted from empire page (commander only)
type EmpireCelestial struct {
Name string
ID CelestialID
Type CelestialType
Fields Fields
Temperature Temperature
Coordinate Coordinate
Resources Resources
Supplies ResourcesBuildings
Facilities Facilities
Defenses DefensesInfos
Researches Researches
Ships ShipsInfos
}
5 changes: 5 additions & 0 deletions extractor_v6.go
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,11 @@ func (e ExtractorV6) ExtractCancelResearchInfos(pageHTML []byte) (token string,
return extractCancelResearchInfosV6(pageHTML)
}

// ExtractEmpire ...
func (e ExtractorV6) ExtractEmpire(pageHTML []byte) ([]EmpireCelestial, error) {
return extractEmpire(pageHTML)
}

// ExtractEmpireJSON ...
func (e ExtractorV6) ExtractEmpireJSON(pageHTML []byte) (interface{}, error) {
return extractEmpireJSON(pageHTML)
Expand Down
137 changes: 136 additions & 1 deletion extracts_v6.go
Original file line number Diff line number Diff line change
Expand Up @@ -1990,7 +1990,9 @@ func extractUniverseSpeedV6(pageHTML []byte) int64 {
return universeSpeed
}

var planetInfosRgx = regexp.MustCompile(`([^\[]+) \[(\d+):(\d+):(\d+)]([\d.,]+)(?i)(?:km|км|公里|χμ) \((\d+)/(\d+)\)(?:de|da|od|mellem|от)?\s*([-\d]+).+C\s*(?:bis|-tól|para|to|à|至|a|~|do|ile|tot|og|до|až|til|la|έως|:sta)\s*([-\d]+).+C`)
var temperatureRgxStr = `([-\d]+).+C\s*(?:bis|-tól|para|to|à|至|a|~|do|ile|tot|og|до|až|til|la|έως|:sta)\s*([-\d]+).+C`
var temperatureRgx = regexp.MustCompile(temperatureRgxStr)
var planetInfosRgx = regexp.MustCompile(`([^\[]+) \[(\d+):(\d+):(\d+)]([\d.,]+)(?i)(?:km|км|公里|χμ) \((\d+)/(\d+)\)(?:de|da|od|mellem|от)?\s*` + temperatureRgxStr)
var moonInfosRgx = regexp.MustCompile(`([^\[]+) \[(\d+):(\d+):(\d+)]([\d.,]+)(?i)(?:km|км|χμ|公里) \((\d+)/(\d+)\)`)
var cpRgx = regexp.MustCompile(`&cp=(\d+)`)

Expand Down Expand Up @@ -2074,6 +2076,139 @@ func extractMoonFromSelectionV6(moonLink *goquery.Selection, b *OGame) (Moon, er
return moon, nil
}

func extractEmpire(pageHTML []byte) ([]EmpireCelestial, error) {
var out []EmpireCelestial
raw, err := extractEmpireJSON(pageHTML)
if err != nil {
return nil, err
}
j, ok := raw.(map[string]interface{})
if !ok {
return nil, errors.New("failed to parse json")
}
planetsRaw, ok := j["planets"].([]interface{})
if !ok {
return nil, errors.New("failed to parse json")
}
for _, planetRaw := range planetsRaw {
planet, ok := planetRaw.(map[string]interface{})
if !ok {
return nil, errors.New("failed to parse json")
}

var tempMin, tempMax int64
temperatureStr := doCastStr(planet["temperature"])
m := temperatureRgx.FindStringSubmatch(temperatureStr)
if len(m) == 3 {
tempMin, _ = strconv.ParseInt(m[1], 10, 64)
tempMax, _ = strconv.ParseInt(m[2], 10, 64)
}
energyStr := doCastStr(planet["energy"])
energyDoc, _ := goquery.NewDocumentFromReader(strings.NewReader(energyStr))
energy := ParseInt(energyDoc.Find("div span").Text())
celestialType := CelestialType(doCastF64(planet["type"]))
out = append(out, EmpireCelestial{
Name: doCastStr(planet["name"]),
ID: CelestialID(doCastF64(planet["id"])),
Type: celestialType,
Fields: Fields{
Built: int64(doCastF64(planet["fieldUsed"])),
Total: int64(doCastF64(planet["fieldMax"])),
},
Temperature: Temperature{
Min: tempMin,
Max: tempMax,
},
Coordinate: Coordinate{
Galaxy: int64(doCastF64(planet["galaxy"])),
System: int64(doCastF64(planet["system"])),
Position: int64(doCastF64(planet["position"])),
Type: celestialType,
},
Resources: Resources{
Metal: int64(doCastF64(planet["metal"])),
Crystal: int64(doCastF64(planet["crystal"])),
Deuterium: int64(doCastF64(planet["deuterium"])),
Energy: energy,
},
Supplies: ResourcesBuildings{
MetalMine: int64(doCastF64(planet["1"])),
CrystalMine: int64(doCastF64(planet["2"])),
DeuteriumSynthesizer: int64(doCastF64(planet["3"])),
SolarPlant: int64(doCastF64(planet["4"])),
FusionReactor: int64(doCastF64(planet["12"])),
SolarSatellite: int64(doCastF64(planet["212"])),
MetalStorage: int64(doCastF64(planet["22"])),
CrystalStorage: int64(doCastF64(planet["23"])),
DeuteriumTank: int64(doCastF64(planet["24"])),
},
Facilities: Facilities{
RoboticsFactory: int64(doCastF64(planet["14"])),
Shipyard: int64(doCastF64(planet["21"])),
ResearchLab: int64(doCastF64(planet["31"])),
AllianceDepot: int64(doCastF64(planet["34"])),
MissileSilo: int64(doCastF64(planet["44"])),
NaniteFactory: int64(doCastF64(planet["15"])),
Terraformer: int64(doCastF64(planet["33"])),
SpaceDock: int64(doCastF64(planet["36"])),
LunarBase: int64(doCastF64(planet["41"])),
SensorPhalanx: int64(doCastF64(planet["42"])),
JumpGate: int64(doCastF64(planet["43"])),
},
Defenses: DefensesInfos{
RocketLauncher: int64(doCastF64(planet["401"])),
LightLaser: int64(doCastF64(planet["402"])),
HeavyLaser: int64(doCastF64(planet["403"])),
GaussCannon: int64(doCastF64(planet["404"])),
IonCannon: int64(doCastF64(planet["405"])),
PlasmaTurret: int64(doCastF64(planet["406"])),
SmallShieldDome: int64(doCastF64(planet["407"])),
LargeShieldDome: int64(doCastF64(planet["408"])),
AntiBallisticMissiles: int64(doCastF64(planet["502"])),
InterplanetaryMissiles: int64(doCastF64(planet["503"])),
},
Researches: Researches{
EnergyTechnology: int64(doCastF64(planet["113"])),
LaserTechnology: int64(doCastF64(planet["120"])),
IonTechnology: int64(doCastF64(planet["121"])),
HyperspaceTechnology: int64(doCastF64(planet["114"])),
PlasmaTechnology: int64(doCastF64(planet["122"])),
CombustionDrive: int64(doCastF64(planet["115"])),
ImpulseDrive: int64(doCastF64(planet["117"])),
HyperspaceDrive: int64(doCastF64(planet["118"])),
EspionageTechnology: int64(doCastF64(planet["106"])),
ComputerTechnology: int64(doCastF64(planet["108"])),
Astrophysics: int64(doCastF64(planet["124"])),
IntergalacticResearchNetwork: int64(doCastF64(planet["123"])),
GravitonTechnology: int64(doCastF64(planet["199"])),
WeaponsTechnology: int64(doCastF64(planet["109"])),
ShieldingTechnology: int64(doCastF64(planet["110"])),
ArmourTechnology: int64(doCastF64(planet["111"])),
},
Ships: ShipsInfos{
LightFighter: int64(doCastF64(planet["204"])),
HeavyFighter: int64(doCastF64(planet["205"])),
Cruiser: int64(doCastF64(planet["206"])),
Battleship: int64(doCastF64(planet["207"])),
Battlecruiser: int64(doCastF64(planet["215"])),
Bomber: int64(doCastF64(planet["211"])),
Destroyer: int64(doCastF64(planet["213"])),
Deathstar: int64(doCastF64(planet["214"])),
SmallCargo: int64(doCastF64(planet["202"])),
LargeCargo: int64(doCastF64(planet["203"])),
ColonyShip: int64(doCastF64(planet["208"])),
Recycler: int64(doCastF64(planet["209"])),
EspionageProbe: int64(doCastF64(planet["210"])),
SolarSatellite: int64(doCastF64(planet["212"])),
Crawler: int64(doCastF64(planet["217"])),
Reaper: int64(doCastF64(planet["218"])),
Pathfinder: int64(doCastF64(planet["219"])),
},
})
}
return out, nil
}

func extractEmpireJSON(pageHTML []byte) (interface{}, error) {
m := regexp.MustCompile(`createImperiumHtml\("#mainWrapper",\s"#loading",\s(.*),\s\d+\s\);`).FindSubmatch(pageHTML)
if len(m) != 2 {
Expand Down
2 changes: 2 additions & 0 deletions interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type Prioritizable interface {
GetCelestials() ([]Celestial, error)
GetCombatReportSummaryFor(Coordinate) (CombatReportSummary, error)
GetDMCosts(CelestialID) (DMCosts, error)
GetEmpire(CelestialType) ([]EmpireCelestial, error)
GetEmpireJSON(nbr int64) (interface{}, error)
GetEspionageReport(msgID int64) (EspionageReport, error)
GetEspionageReportFor(Coordinate) (EspionageReport, error)
Expand Down Expand Up @@ -383,6 +384,7 @@ type Extractor interface {
ExtractFleetDeutSaveFactor(pageHTML []byte) float64
ExtractCancelBuildingInfos(pageHTML []byte) (token string, techID, listID int64, err error)
ExtractCancelResearchInfos(pageHTML []byte) (token string, techID, listID int64, err error)
ExtractEmpire(pageHTML []byte) ([]EmpireCelestial, error)
ExtractEmpireJSON(pageHTML []byte) (interface{}, error)
ExtractCharacterClass(pageHTML []byte) (CharacterClass, error)
ExtractCharacterClassFromDoc(doc *goquery.Document) (CharacterClass, error)
Expand Down
22 changes: 22 additions & 0 deletions ogame.go
Original file line number Diff line number Diff line change
Expand Up @@ -3053,6 +3053,23 @@ func (b *OGame) executeJumpGate(originMoonID, destMoonID MoonID, ships ShipsInfo
return true, 0, nil
}

func (b *OGame) getEmpire(celestialType CelestialType) (out []EmpireCelestial, err error) {
var planetType int
if celestialType == PlanetType {
planetType = 0
} else if celestialType == MoonType {
planetType = 1
} else {
return out, errors.New("invalid celestial type")
}
vals := url.Values{"page": {"standalone"}, "component": {"empire"}, "planetType": {strconv.Itoa(planetType)}}
pageHTMLBytes, err := b.getPageContent(vals)
if err != nil {
return out, err
}
return b.extractor.ExtractEmpire(pageHTMLBytes)
}

func (b *OGame) getEmpireJSON(nbr int64) (interface{}, error) {
// Valid URLs:
// /game/index.php?page=standalone&component=empire&planetType=0
Expand Down Expand Up @@ -5687,6 +5704,11 @@ func (b *OGame) HeadersForPage(url string) (http.Header, error) {
return b.WithPriority(Normal).HeadersForPage(url)
}

// GetEmpire gets all planets/moons information resources/supplies/facilities/ships/researches
func (b *OGame) GetEmpire(celestialType CelestialType) ([]EmpireCelestial, error) {
return b.WithPriority(Normal).GetEmpire(celestialType)
}

// GetEmpireJSON retrieves JSON from Empire page (Commander only).
func (b *OGame) GetEmpireJSON(nbr int64) (interface{}, error) {
return b.WithPriority(Normal).GetEmpireJSON(nbr)
Expand Down
18 changes: 18 additions & 0 deletions ogame_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3043,6 +3043,24 @@ func TestFixAttackEvents(t *testing.T) {
assert.Equal(t, PlanetType, attacks[0].Destination.Type) // Did not change
}

func TestExtractEmpirePlanets(t *testing.T) {
pageHTMLBytes, _ := ioutil.ReadFile("samples/v8.1/en/empire_planets.html")
res, _ := NewExtractorV6().ExtractEmpire(pageHTMLBytes)
assert.Equal(t, 8, len(res))
assert.Equal(t, Coordinate{Galaxy: 4, System: 208, Position: 8, Type: PlanetType}, res[0].Coordinate)
assert.Equal(t, int64(-3199), res[0].Resources.Energy)
}

func TestExtractEmpireMoons(t *testing.T) {
pageHTMLBytes, _ := ioutil.ReadFile("samples/v8.1/en/empire_moons.html")
res, _ := NewExtractorV6().ExtractEmpire(pageHTMLBytes)
assert.Equal(t, 3, len(res))
assert.Equal(t, Coordinate{Galaxy: 4, System: 116, Position: 9, Type: MoonType}, res[0].Coordinate)
assert.Equal(t, int64(0), res[0].Resources.Energy)
assert.Equal(t, int64(-19), res[0].Temperature.Min)
assert.Equal(t, int64(21), res[0].Temperature.Max)
}

func TestExtractAuction_playerBid(t *testing.T) {
pageHTMLBytes, _ := ioutil.ReadFile("samples/v7.5.0/en/auction_player_bid.html")
res, _ := NewExtractorV6().ExtractAuction(pageHTMLBytes)
Expand Down
7 changes: 7 additions & 0 deletions prioritize.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,13 @@ func (b *Prioritize) HeadersForPage(url string) (http.Header, error) {
return b.bot.headersForPage(url)
}

// GetEmpire (Commander only)
func (b *Prioritize) GetEmpire(celestialType CelestialType) ([]EmpireCelestial, error) {
b.begin("GetEmpire")
defer b.done()
return b.bot.getEmpire(celestialType)
}

// GetEmpireJSON retrieves JSON from Empire page (Commander only).
func (b *Prioritize) GetEmpireJSON(nbr int64) (interface{}, error) {
b.begin("GetEmpireJSON")
Expand Down
Loading

0 comments on commit 9634fef

Please sign in to comment.