Code Monkey home page Code Monkey logo

viseur's Introduction

Viseur

Visualizer for the Cadre AI game framework.

Viseur is a single page application that is accessed via web browser. It is basically a glorified log file viewer, and parses gamelogs and makes pretty graphics showing to humans what happend in that log.

Note: A pre-built version of the master branch is hosted at http://vis.siggame.io/.

Features

  • Playback of gamelogs from local files, or remote sources
  • Games rendered via WebGL
  • A single Viseur instance can have multiple game "modules" to be able to parse and playback different games, much like all Cadre applications
  • Supports spectator mode for all games out of the box
  • Developers can code UIs for to make any Cadre game human playable
  • Nifty transitions to look sweet
  • All settings customizable to end users and settings persist between page reloads

Technical Details

Viseur is a TypeScript application modeled off Node.js design paradigms, with CSS and HTML heavily utilized.

  • TypeScript: wrapped up by Webpack to allow a Node.js like runtime environment.
  • CSS: SASS (Syntactically Awesome Style Sheets). It's all valid CSS3, but with the hotness SASS brings in.
  • HTML: Still raw HTML (no Jade or something like that), but we use Handlebars to template the HTML.
  • JSDoc documentation: All code documented using JSDoc style for proper documentation generation.

Requirements

Before building, you must have Node/NPM installed. That is the only requirement to build, though we do have suggested IDEs below.

Installation

  1. Install Node.js: download and install Node.js. Node comes with NPM (Node Package Manager) so that covers all the software you need to install normally, everything else from this point on is done via Node stuff.
  2. Clone this repo using git: In whatever directory you want to work out of do git clone https://github.com/siggame/Viseur.git
  3. Install Viseur dependencies: navigate to the Viseur directory you just cloned and then run npm install. This reads the package.json file and downloads all the modules it requires. If that file is ever changed, just re-run npm install.
  4. Statup the development server using npm start
  5. In browser, go to http://localhost:8080.

Committing

  1. Type: 'npm run lint' to run the linter
  2. If you get CRLF and LF error run 'npm run fix' then repeat step 1
  3. Fix errors and repeat step 1 on ward until format is correct before you commit
  4. commit

Deploying

The travis file is setup to automatically build and deploy the visualizer assets to the gh-docs branch so they can be served to http://vis.siggame.io/. Generally this is the only way you should

Never deploy Viseur using npm start, as that starts up a webpack-dev-server, which listens for file changes and rebuilds webpack.

Instead, the whole point of webpack is to build all our sources into a few files so browsers do not need to make >100 HTTP Requests for all our files.

Run npm run build.

Grab all the files in the index of Viseur, and serve them via some simple HTTP file server. http-server works well for this.

Recommended Dev Environment

You are free to use whatever development environment you want to work in Viseur, but we do have a recommended one.

Visual Studio Code

With the following extensions:

Those tools will help analyze your code and catch errors early, before you find them in run time.

Open the root directory you cloned down (Viseur) in VSC, and it will know everything else to setup and run correctly.

With VSC installed you can use the integrated terminal to follow the above build steps, while the IDE analyzes your code for errors as you type!

viseur's People

Contributors

anoghastra avatar atruong58 avatar cazadorro avatar elk8kh avatar jacobfischer avatar jawbone999 avatar jeffreystrahm avatar joshuapondrom avatar jschultz1995 avatar jzaustin295 avatar lanchauletran avatar leoflaker avatar mastercash avatar matthewqualls avatar michael-beaver avatar numbreon avatar reginaldjefferywatson avatar renodubois avatar russleyshaw avatar tehpers avatar vilhelm1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

viseur's Issues

Thread delta state changes

One of the most expensive operations is when the game state changes, because we have to merge delta state(s), then tell the BaseGameObject instances that they have updated so they can update sprites and such.

This leads to micro stuttering between frames when a merge occurs, and the UI locks up.

Instead, we should use web workers to throw that expensive load to another thread, so the UI does not stutter.

Arena + Presentation mode does not work

If you go to arena mode, give it a valid url, and make sure presentation mode remains checked, it will not enter presentation mode upon refresh.

This is because the &presentation url parameter does not get set. This appears to be because the FileTab.presentationInput.value is always false, regardless if it is checked.

This is probably a simple fix, but I don't have time at the moment to investigate it.

Update title based on gamelog playing

Currently the title of the page is static, Viseur

It would be cool to update the title. Say for example we were playing back the gamelog 2017.03.23.12.29.15.006-Chess-1

Once parsed, we know the gamelog will be

game: Chess
session: 1
date: 2017.03.23.12.29.15.006

So, we can then make the title Viseur - Chess - 1 - <formatted date>

That way if you have multiple gamelogs open, you can easily tell what they are for.

An expansion on this idea would be to update the favicon as well depending on game. But that is outside the scope of this issue.

Local Gamelog playback

The file input for local gamelogs, while present, is not hooked up. It will need to read the local file.

For now assume the file is JSON, and not gzipped json. The endpoint for users to save gamelogs should be through Viseur, and so we should never let them save gzipped json in the first place.

Visualizer randomly pauses

The visualizer will randomly pause, and must be manually unpaused by clicking the pause/unpause button.

From src/viseur/time-manager.ts

        this.viseur.gui.events.playbackSlide.on((value) => {
            const index = Math.floor(value);
            const dt = value - index;
            const current = this.getCurrentTime();
            if (Math.abs(value - current.index - current.dt) > 0.10) {
                // the change in time was too great, they probably clicked far away
                this.pause(index, dt);
            }
        });

While the intent of this code is to pause the visualizer when the user clicks on the slider, it seems to also trigger randomly because the slider is not always in sync with the timer.

I'm not sure of the reason for the desynchronization, the pauses are always at different deltas even for the same gamelog, so I'm inclined to believe there is some sort of race condition.

A proper fix would distinguish human-generated clicks on the slider from programmatic changes to the slider's value, however the necessary information to distinguish (event.isTrusted) does not seem to be piped through.

An easier fix would be to replace
this.pause(index, dt);
with
this.setTime(index, dt);
So that changes to the slider never cause a pause. If the user wants to jump to a specific point while paused, they can simply pause, and then click.

Spectator Mode

Spectator mode is essentially playing parsing a gamelog that is streamed to you as it is created.

Playback by the user is disabled, instead they... well... spectate. When a delta comes in, animate it. Then wait for the next delta.

Most of this involves actually communicating to Cerveau and interpreting its I/O. Thankfully, Cerveau already supports WebSockets as an IO endpoint.

Chess - Right Click Error

In Chess during human playable mode right click, and you might get the following error:

Uncaught TypeError: Cannot read property 'file' of null(…)

Is Max.max a typo?

Should this be Math.max?

offset = Max.max(Math.abs(offset || 0), this.length);

    last: function(offset) {
        offset = Max.max(Math.abs(offset || 0), this.length);
        return this[this.length - 1 - offset];
    },

Add Dockerfile

Including a dockerfile would make it easy for us to have automated docker builds directly out of Docker Hub. This would be really beneficial if we start running everything on Google's Container Engine.

Missing JSDocs

I got lazy and did not include proper JSDoc styled documentation in all source code. Need to do that.

Also include instructions on running JSDoc to generate documentation.

Human playable mode: second players first delta is wrong

It happens in chess, but probably all games for streaming gamelogs.

  1. Connect two chess human clients.
  2. Have white (the first player) make a move.
  3. white player will render correctly
  4. black player will not

It appears as if the second player animates the delta "backwards", where the currentState and nextState are reversed, so the move is played back in reverse and it sits in the start position instead of the end.

Any subsequent deltas to that piece are correct though. So it's something with initiation.

Human Playable Mode

This requires #2 to be done first, as essentially you now send run commands to the server and spectate the results. New UI features will need to be added.

This is essentially a Chess only features, but should be made generic enough that if devs want a future MegaMinerAI to be human playable they can add that feature to the game plugin.

Fullscreen Infopane not hidden

When the visualizer is in full screen, the Info Pane, while hidden, is still taking up space.

This should not be the case. It's probably a renderer math bug where it is taking into account the infopane's size when it is hidden.

Version Upgrades

Babel 7 and TypeScript 3 are out. They should be used.

In addition with the Cerveau V2 TypeScript re-write the Creer based types can support much more robust type features.

Turn by Turn playback

Gamelogs are delta by delta, so playback of delta by delta was naturally the simplest, and correctly displays how the game actually played out.

However, often for turn based games most of what happens in 1 delta will not affect the other game objects, so delta by delta can feel boring and slow.

Turn by Turn would be an optional playback mode in games that are turn based. In these, we "flatten" all deltas to be animated over the course of 1 "turn".

This would naturally be tricky. As during 1 turn some unit A could have 100 different Deltas, while others may just have 1 Deltas. We'd then have to figure out how to animate units at different rate, and then there could be more complex situations like determining how many times exactly is was effected?

This will be exceptionally tricky, if not impossible.

Another way, that looses game information would be to just flatten deltas based on turns. So, if you have 100 deltas per turn, you would just take the delta 0 for the start of the turn, and delta 100 for the end of the turn. Deltas 1, 2, ..., 99 are dropped out.

Again, this is lossy compression, and less desirable. However, it may be the only realistic solution.

Issue With Catastrophe displaying Monuments everywhere.

In the structure file for the viseur for catastrophe, the setup for what sprite to select to display is structured wrong. The constructor is a collection of ifs but the last statement is an else. The actual structure should be if, else if, else if, else.
Location
at lines: 67-85

Backport old games

Backport MegaMinerAI17: Spiders and/or MegaMinerAI 16: Anarchy, for more example for future devs.

Human client timeout error message incorrect

When playing as a human client, if run out of time a fatal message is sent from the server.

The error message currently is confusing due to a lack of a string.format call. However fixing this causes the error to disappear after about a second, which is less useful.

In addition, when a game ends (or you timeout). the ticker should stop ticking. It might be good to update the player pane that they timedout as well.

Chess - Show moves list

As in siggame/Chesser show somewhere on the GUI should show the SAN moves.

Not sure where...

Another solution would be to allow spectator mode to replay moves so they can roll back the time.

Ignore deltas without animations

Currently, all deltas are "played" even if there is no animation width the delta. This greatly slows down the rate of playback, particularly if a client generates many errors.

These deltas should never update relevant game structures because if an animation isn't played generally only back-end stuff will be updated. It may still be better to supply an option to play them / only play them if an option is selected and the inspect tab is open.

Arena Mode

Arena mode should endlessly play gamelogs from the Arena.

  1. Page loads, everything initializes
  2. Go to some remote arena endpoint, get a gamelog
  3. Play it back, disable playback controls
  4. When done wait a few seconds, then refresh the browser (which then goes back to 1, and would grab any updates to the visualizer on refresh).

This will be easy, but requires the arena to have the endpoint defined or made.

Dismissable Error Modals

Sometimes error modals do not mean the whole thing is borked. Allow those modals to be dismissed (closed)

Voting

Have a way (preferably a really easy way, competitors are lazy) for viewers to vote on the 'excitingness/interestingness' of a game. Send that data somewhere where the arena can get at it.

Creer templates

Once the game specific code is mature, convert them to Creer templates so that new games can be automatically added along with the game server & clients.

Delta merge error on new game objects

A delta merge error can occur given the following sequence of events:

  • a new game object is created
  • it is added as references in multiple locations in a game structure
  • depending on the order keys are iterated in the delta, the game object may not be known to be new, and thus set to undefined till seen

Need to create all new unseen game obejcts before complete delta merge.
Thanks to @MasterCash for bringing to my attention.

Inspect tab performance issues

Currently the Inspect tab is by far the largest performance hog. Profiles done in Chrome show it taking up ~83% of the time used "rendering" the game just updating the DOM from the inspect tab's code.

This is not too surprising, the inspect tree represents the entire game structure as a tree of DOM elements, and large games can have a tree with a branching factor in the tens of thousands.

The easiest solution would be to just drop the inspect tree entirely. But I don't think that is worth it.

Instead we should turn to some technique like virtualization, where DOM elements not being rendered are not even added to the document. it's a bit hackish, but it can have HUGE speedups. We could also employ types of lazy loading, where if a node is not expanded don't even build it's DOM elements until (if) the user expands them.

This is not a trivial rewrite, but it will be needed to keep Viseur performant.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.