Python library for creating and parsing HSReplay XML files

Overview

python-hsreplay

Build Status PyPI

A python module for HSReplay support.

https://hearthsim.info/hsreplay/

Installation

The library is available on PyPI. pip install hsreplay will install it.

Dependencies:

  • hearthstone
  • hslog
  • lxml (optional) for faster XML parsing and writing. Will use xml.etree if not available.
  • aniso8601 or dateutil for timestamp parsing

Usage

The main document class is hsreplay.document.HSReplayDocument. That class contains all the necessary functionality to import and export HSReplay files.

Reading/Writing HSReplay XML files

The classmethod from_xml_file(fp) takes a file-like object and will return a document. If you already have an ElementTree object, you can call the from_xml(xml) classmethod instead.

To export to an HSReplay XML document, the HSReplayDocument.toxml(pretty=False) method can be used to obtain a UTF8-encoded string containing the document.

Reading directly from a log file

The library integrates directly with the python-hearthstone library to produce HSReplayDocument objects directly from a log file or a parser instance.

Use the helper classmethods from_log_file(fp, processor="GameState", date=None, build=None) and from_parser(parser, build=None), respectively.

Exporting back to a PacketTree

It is possible to export HSReplayDocument objects back into a PacketTree with the to_packet_tree() method. This therefore allows lossless conversion from a PacketTree, into HSReplayDocument, then back into a PacketTree.

This is especially interesting because of the native functionality in python-hearthstone which is able to export to a Game tree and allows exploring the game state. By converting HSReplayDocument objects to a PacketTree, it's very easy to follow the replay at a gameplay level, explore the state of the various entities and even hook into the exporter in order to programmatically analyze it.

Comments
  • Difference between c# and python implementation of Options?

    Difference between c# and python implementation of Options?

    In c#, OptionsHandler forces options to be at the root of the element:

    var match = Regexes.OptionsEntityRegex.Match(data);
    if(match.Success)
    {
        var id = match.Groups[1].Value;
        state.Options = new Options {Id = int.Parse(id), OptionList = new List<Option>(), TimeStamp = timestamp};
        state.UpdateCurrentNode(typeof(Game));
        if(state.Node.Type == typeof(Game))
            ((Game)state.Node.Object).Data.Add(state.Options);
        else
            throw new Exception("Invalid node " + state.Node.Type + " -- " + data);
        return;
    }
    

    The effect of this is that if you are within an Action, the Options node will cause the parser to set the current node as the Game, and all subsequent calls will be added to the Game, instead of the previous Action node.

    I don't know enough Python to point out where in the code that happens, but looking at the attached files you can clearly see at line 793 that the output XML diverges

    python.out.xml.txt csharp.out.xml.txt

    The initial log is also attached, and from reading it (line 878 is where the option is declared), there seems to be no reason not to attach the Options to the root Action instead of the Game node.

    Power_2.log.txt

    So my question is: what is the correct output?

    Thanks!

    csharp python 
    opened by sebastientromp 7
  • Player names missing when converting reconnected games

    Player names missing when converting reconnected games

    In the second game (after the reconnect).

    powerlog: http://files.hsdecktracker.net/powerlog.txt hsreplay: http://hsreplay.net/joust/replay/d43a810d-3b40-419f-ad8b-0aa57a47cc31

    opened by azeier 6
  • Importing output_log: object has not attribute 'game'

    Importing output_log: object has not attribute 'game'

    Hey,

    I've tried to generate an hsreplay from the output_log.txt file, but got a 'PowerLogParser' object has no attribute 'game', and indeed it looks like the generated log files miss the game declaration at the beginning (I've attached an example of output_log.txt I get using HDT).

    Is there something to configure that I've missed?

    Thanks,
    Seb

    hdt 
    opened by sebastientromp 5
  • HDT integration

    HDT integration

    • [x] Add command line argument to use PowerTaskList
    • [x] Add frozen script download to releases (cx_freeze)

    Also: Do we want to keep the csharp implementation on this repo (will most likely not be maintained)?

    python 
    opened by azeier 4
  • Added feature, converting all hdtreplay in folder to hsreplay

    Added feature, converting all hdtreplay in folder to hsreplay

    I add a new features and a bash system

    main.py -all [folder](will convert all files in .hdtreplay in hsreplays files %28 without spaces in the name %29) main.py -help ( display help )

    opened by PierreBanwarth 4
  • AttributeError: 'str' object has no attribute 'isoformat'

    AttributeError: 'str' object has no attribute 'isoformat'

    Traceback (most recent call last):
      File "python/convert.py", line 13, in <module>
        main()
      File "python/convert.py", line 9, in main
        print(log_to_xml(f))
      File "/home/benedict/Dokumente/HSReplay/python/hsreplay/__init__.py", line 314, in log_to_xml
        root.append(game_element.xml())
      File "/home/benedict/Dokumente/HSReplay/python/hsreplay/__init__.py", line 50, in xml
        element.append(node.xml())
      File "/home/benedict/Dokumente/HSReplay/python/hsreplay/__init__.py", line 50, in xml
        element.append(node.xml())
      File "/home/benedict/Dokumente/HSReplay/python/hsreplay/__init__.py", line 59, in xml
        element.attrib["ts"] = self.ts.isoformat()
    AttributeError: 'str' object has no attribute 'isoformat'
    

    Power.log.

    python 
    opened by beheh 3
  • c# testdata - Power_2.log.txt vs Power_2.log.xml

    c# testdata - Power_2.log.txt vs Power_2.log.xml

    In Power_2.log.txt, starting from line 558, you can see (in order):

    • ACTION_START
    • Choices
    • TAG_CHANGE
    • Choices
    • TAG_CHANGE
    • ACTION_START
    • ACTION_END
    • etc.

    The XML present in the test data however doesn't nest these elements, and produces:

    <Action entity="1" index="-1" type="5">
        <TagChange entity="3" tag="305" value="1"/>
        <Choices entity="1" max="3" min="0" playerID="1" source="1" type="MULLIGAN">
            <Choice entity="8" index="0"/>
            <Choice entity="16" index="1"/>
            <Choice entity="33" index="2"/>
        </Choices>
    </Action>
    <TagChange entity="2" tag="305" value="1"/>
    <Choices entity="2" max="5" min="0" playerID="2" source="1" type="MULLIGAN">
        <Choice entity="54" index="0"/>
        <Choice entity="49" index="1"/>
        <Choice entity="55" index="2"/>
        <Choice entity="43" index="3"/>
        <Choice entity="68" index="4"/>
    </Choices>
    

    while I would expect something like

    <Action entity="1" index="-1" target="0" ts="01:41:27.9112918" type="5">
        <TagChange entity="2" tag="305" value="1"/>
        <Choices entity="1" max="3" min="0" playerID="1" source="1" taskList="0" ts="01:41:27.9312929" type="1">
            <Choice entity="8" index="0"/>
            <Choice entity="16" index="1"/>
            <Choice entity="33" index="2"/>
        </Choices>
        <TagChange entity="3" tag="305" value="1"/>
        <Choices entity="2" max="5" min="0" playerID="2" source="1" taskList="0" ts="01:41:28.0212980" type="1">
            <Choice entity="54" index="0"/>
            <Choice entity="49" index="1"/>
            <Choice entity="55" index="2"/>
            <Choice entity="43" index="3"/>
            <Choice entity="68" index="4"/>
        </Choices>
        <TagChange entity="2" tag="305" value="2"/>
        <Action entity="2" index="-1" target="0" ts="01:41:47.1423917" type="5">
            <TagChange entity="25" tag="49" value="3"/>
            <TagChange entity="25" tag="263" value="1"/>
            <TagChange entity="8" tag="49" value="2"/>
            <TagChange entity="8" tag="263" value="0"/>
            <TagChange entity="28" tag="49" value="3"/>
            <TagChange entity="28" tag="263" value="2"/>
            <TagChange entity="16" tag="49" value="2"/>
            <TagChange entity="16" tag="263" value="0"/>
            <TagChange entity="2" tag="305" value="3"/>
        </Action>
            ...
    

    Is this the intended behaviour?

    Thanks!

    Seb

    csharp 
    opened by sebastientromp 3
  • [Feature Request]  Attack direction arrows

    [Feature Request] Attack direction arrows

    Twould make it even more intuitive when watching a game if arrows appeared between a minion or character making an attack and the intended target of their attack.

    Optional but useful: A arrow that displays redirected attacks caused by secrets, certain minions on the board, etc. (Ie; minion A attacks minion B, but then the paladin secret causes the minion to redirect to the summoned 2/1.)

    duplicate 
    opened by sdlorimor 2
  • [Feature Request] Make in-play secrets viewable

    [Feature Request] Make in-play secrets viewable

    When watching replays, please it possible to mouse over the "?" logo for secrets on the character portrait to see what secrets are in play.

    Or better yet, come up with a way to display which secrets are currently in effect so mousing over isn't necessary.

    Otherwise it's a small nightmare trying to remember which secrets are currently in play when reviewing games with secret-heavy players.

    duplicate 
    opened by sdlorimor 2
  • Fix end turn option not being added to the options list

    Fix end turn option not being added to the options list

    This fixes DTD validation errors caused by empty options lists, which occur when ending the turn is the only option. The END_TURN option is added with entity = 0 as demanded by the DTD. Exemplary log line: GameState.DebugPrintOptions() - option 0 type=END_TURN mainEntity=

    opened by riQQ 2
  • Current node not updated when processing HideEntity regex (c#)?

    Current node not updated when processing HideEntity regex (c#)?

    Hey,

    In DataHandler.cs, there is:

    match = Regexes.ActionHideEntityRegex.Match(data);
    if(match.Success)
    {
        var rawEntity = match.Groups[1].Value;
        var tagName = match.Groups[2].Value;
        var value = match.Groups[3].Value;
        var entity = Helper.ParseEntity(rawEntity, state);
        var zone = Helper.ParseTag(tagName, value);
        var hideEntity = new HideEntity {Entity = entity, Zone = zone.Value, TimeStamp = timestamp};
        if(state.Node.Type == typeof(Game))
            ((Game)state.Node.Object).Data.Add(hideEntity);
        else if(state.Node.Type == typeof(Action))
            ((Action)state.Node.Object).Data.Add(hideEntity);
        else
            throw new Exception("Invalid node: " + state.Node.Type);
        return;
    }
    

    Contrary to all the other processes, there is no call to state.UpdateCurrentNode(typeof(Game), typeof(Action)); before checking the type of the current node. Is this intentional?

    csharp 
    opened by sebastientromp 2
  • Replacing SendChoices by ChosenEntities

    Replacing SendChoices by ChosenEntities

    The SendChoiceselement we get from GameState.SendChoices is very symmetrical to ChosenEntities (GameState.DebugPrintEntitiesChosen), which we only get from other players. The problem is that we don't get the exactly the same data in each case, so we have to keep them separate for now.

    Ideally we should use ChosenEntities for both. But then we lack the choice type.. this would require some changes on Blizzard's side.

    blizzard-plz 
    opened by jleclanche 0
Owner
HearthSim
Hearthstone Simulation, reverse engineering and more
HearthSim
Python library for parsing Godot scene files

Godot Parser This is a python library for parsing Godot scene (.tscn) and resource (.tres) files. It's intended to make it easier to automate certain

Steven Arcangeli 30 Jan 4, 2023
These are After Effects and Python files that were made in the process of creating the video for the contest.

spirograph These are After Effects and Python files that were made in the process of creating the video for the contest. In the python file you can qu

null 91 Dec 7, 2022
App and Python library for parsing, writing, and validation of the STAND013 file format.

python-stand013 python-stand013 is a Python app and library for parsing, writing, and validation of the STAND013 file format. Features The following i

Oda 3 Nov 9, 2022
Make creating Excel XLSX files fun again

Poi: Make creating Excel XLSX files fun again. Poi helps you write Excel sheet in a declarative way, ensuring you have a better Excel writing experien

Ryan Wang 11 Apr 1, 2022
Python library for creating PEG parsers

PyParsing -- A Python Parsing Module Introduction The pyparsing module is an alternative approach to creating and executing simple grammars, vs. the t

Pyparsing 1.7k Jan 3, 2023
Grimoire is a Python library for creating interactive fiction as hyperlinked html.

Grimoire Grimoire is a Python library for creating interactive fiction as hyperlinked html. Installation pip install grimoire-if Usage Check out the

Scott Russell 5 Oct 11, 2022
Age of Empires II recorded game parsing and summarization in Python 3.

mgz Age of Empires II recorded game parsing and summarization in Python 3. Supported Versions Age of Kings (.mgl) The Conquerors (.mgx) Userpatch 1.4

null 148 Dec 11, 2022
Simple web application, which has a single endpoint, dedicated to annotation parsing and convertion.

Simple web application, which has a single endpoint, dedicated to annotation parsing and conversion.

Pavel Paranin 1 Nov 1, 2021
A quick experiment to demonstrate Metamath formula parsing, where the grammar is embedded in a few additional 'syntax axioms'.

Warning: Hacked-up code ahead. (But it seems to work...) What it does This demonstrates an idea which I posted about several times on the Metamath mai

Marnix Klooster 1 Oct 21, 2021
Automates the fixing of problems reported by yamllint by parsing its output

yamlfixer yamlfixer automates the fixing of problems reported by yamllint by parsing its output. Usage This software automatically fixes some errors a

OPT Nouvelle Caledonie 26 Dec 26, 2022
A visidata plugin for parsing f5 ltm/gtm/audit logs

F5 Log Visidata Plugin This plugin supports the default log format for: /var/log/ltm* /var/log/gtm* /var/log/apm* /var/log/audit* It extracts common l

James Deucker 1 Jan 6, 2022
Python module for creating the circuit simulation definitions for Elmer FEM

elmer_circuitbuilder Python module for creating the circuit simulation definitions for Elmer FEM. The circuit definitions enable easy setup of coils (

null 5 Oct 3, 2022
Collaboration project to creating bank application maded by Anzhelica Sakun and Yuriy Konyukh

Collaboration project to creating bank application maded by Anzhelica Sakun and Yuriy Konyukh

Yuriy 1 Jan 8, 2022
In the works, creating a new Chess Board and way to Play...

sWJz4Chess date started on github.com 11-13-2021 In the works, creating a new Chess Board and way to Play... starting to write this in Pygame, any ind

Shawn 2 Nov 18, 2021
Stopmagic gives you the power of creating amazing Stop Motion animations faster and easier than ever before.

Stopmagic gives you the power of creating amazing Stop Motion animations faster and easier than ever before. This project is maintained by Aldrin Mathew.

Aldrin's Art Factory 67 Dec 31, 2022
Framework for creating efficient data processing pipelines

Aqueduct Framework for creating efficient data processing pipelines. Contact Feel free to ask questions in telegram t.me/avito-ml Key Features Increas

avito.tech 137 Dec 29, 2022
Attempt at creating organized collection of little handy snippets of code I'm receiving along the way

ChaosCode Attempt at creating organized collection of little handy snippets of code I'm receiving along the way I always considered coding and program

INFU 4 Nov 26, 2022
A script for creating battle animations in FEGBA format.

AA2 Made by Huichelaar. I heavily referenced FEBuilderGBA. I also referenced circleseverywhere's Animation Assembler. This is also where I took lzss.p

null 2 May 31, 2022
Bootstraparse is a personal project started with a specific goal in mind: creating static html pages for direct display from a markdown-like file

Bootstraparse is a personal project started with a specific goal in mind: creating static html pages for direct display from a markdown-like file

null 1 Jun 15, 2022