happyleavesaoc / aoc-mgz

Age of Empires II recorded game parsing and summarization in Python 3.
MIT License
197 stars 41 forks source link

Unable to run any of the examples provided on the main page #76

Closed Guimoute closed 2 years ago

Guimoute commented 2 years ago

Hello,

For some reason, I cannot run any of the examples provided on the main page. Are there special requirements that are not listed? My python version is 3.8.7.
Here is a simple script that is used to test the five examples and log the error traceback to a file. All you need to change is EXAMPLE = 1|2|3|4|5 in the constants.

# Imports.
import mgz
import os

# Constants.
PATH = "test.aoe2record"
EXAMPLE = 5

# Redirect the error to a file.
with open(f"log_example_{EXAMPLE}.txt", "w") as log_file:

    # Open a game and get information.
    try:
        with open(PATH, "rb") as data:

            if EXAMPLE == 1:
                from mgz import header, body
                eof = os.fstat(data.fileno()).st_size
                header.parse_stream(data)
                body.meta.parse_stream(data)
                while data.tell() < eof:
                    body.operation.parse_stream(data)

            elif EXAMPLE == 2:
                from mgz import header, fast
                eof = os.fstat(data.fileno()).st_size
                header.parse_stream(data)
                fast.meta(data)
                while data.tell() < eof:
                    fast.operation(data)

            elif EXAMPLE == 3:
                from mgz.summary import Summary
                s = Summary(data)
                s.get_map()
                s.get_platform()

            elif EXAMPLE == 4:
                from mgz.model import parse_match
                match = parse_match(data)
                match.map.name
                match.file.perspective.number

            elif EXAMPLE == 5:
                import json
                from mgz.model import parse_match, serialize
                match = parse_match(data)
                print(json.dumps(serialize(match), indent=2))

    except Exception:
        import traceback
        log_file.write(traceback.format_exc())

test.zip contains test.aoe2record.

Manually looking at the header, this game has the following characteristics:

data = open(test.aoe2record, "rb")
from mgz.summary import *
header = decompress(data)
version, game, save, log = parse_version(header, data)
>>> version = <Version.DE: 21>
>>> game = 'VER 9.4'
>>> save = 25.22
>>> log = 5

The 5 tracebacks are here: log_example_1.txt log_example_2.txt log_example_3.txt log_example_4.txt log_example_5.txt

The 5 top-most errors are:

construct.core.ConstError: expected b'\x00\x0b' but parsed b'\x00\x00'

construct.core.ConstError: expected b'\x00\x0b' but parsed b'\x00\x00'

construct.core.ConstError: expected b'\x00\x0b' but parsed b'\x00\x00'

  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz\fast\header.py", line 48, in de_string
    assert data.read(2) == b'\x60\x0a'
AssertionError

  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz\fast\header.py", line 48, in de_string
    assert data.read(2) == b'\x60\x0a'
AssertionError

Thank you in advance for your help.

happyleavesaoc commented 2 years ago

Are you using the latest version of mgz? You'll need to git clone the repository to get it.

Guimoute commented 2 years ago

I updated construct from 2.8.16 to 2.10.68 and now import mgz causes an error, so I cannot check the version. I got it via pip though, not on github. I'll try with github.

ImportError: cannot import name 'Embedded' from 'construct' (C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\construct\__init__.py)

Edit: it was mgz-1.7.3 that I got via pip. I am installing 1.7.4 right now.

Guimoute commented 2 years ago

I reverted the construct upgrade.

With a manual install of mgz-1.7.4 I have the three first examples that work. Examples 4 and 5 yield a different error now.

Traceback (most recent call last):
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 463, in parse
    players, mod = parse_players(header, num_players, version)
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 430, in parse_players
    players = [parse_player(header, number, num_players) for number in range(num_players)]
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 430, in <listcomp>
    players = [parse_player(header, number, num_players) for number in range(num_players)]
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 116, in parse_player
    name, resources = unpack(f'<{name_length - 1}s2xIx', header)
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 33, in unpack
    output = struct.unpack(fmt, data.read(struct.calcsize(fmt)))
struct.error: bad char in struct format

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "REDACTED/PATH/TO/MY/PROGRAM", line 49, in <module>
    match = parse_match(data)
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\model\__init__.py", line 93, in parse_match
    data = parse(handle)
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 467, in parse
    raise RuntimeError("could not parse")
RuntimeError: could not parse
Traceback (most recent call last):
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 463, in parse
    players, mod = parse_players(header, num_players, version)
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 430, in parse_players
    players = [parse_player(header, number, num_players) for number in range(num_players)]
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 430, in <listcomp>
    players = [parse_player(header, number, num_players) for number in range(num_players)]
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 116, in parse_player
    name, resources = unpack(f'<{name_length - 1}s2xIx', header)
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 33, in unpack
    output = struct.unpack(fmt, data.read(struct.calcsize(fmt)))
struct.error: bad char in struct format

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "REDACTED/PATH/TO/MY/PROGRAM", line 56, in <module>
    match = parse_match(data)
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\model\__init__.py", line 93, in parse_match
    data = parse(handle)
  File "C:\WPy64-3870\python-3.8.7.amd64\lib\site-packages\mgz-1.7.4-py3.8.egg\mgz\fast\header.py", line 467, in parse
    raise RuntimeError("could not parse")
RuntimeError: could not parse
Guimoute commented 2 years ago

All the dependencies were installed properly apparently.

![dependencies done](https://user-images.githubusercontent.com/51537797/161320485-0c4fbbb3-433f-4f91-8718-65f71a2aa35c.png)
happyleavesaoc commented 2 years ago

Ok, now you are seeing expected behavior. 4 and 5 (relying on "fast mode") aren't compatible with the latest version of DE, yet. You'll want to use the "full mode"/Summary to parse the latest recs.

Guimoute commented 2 years ago

Ok, thank you so much for your fast reply!