Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
quentinms committed Nov 24, 2015
0 parents commit eed0ce0
Show file tree
Hide file tree
Showing 18 changed files with 921 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eGMR-darwin-x64/*
node_modules/*
4 changes: 4 additions & 0 deletions app/config/gmr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"saveFile": "",
"authKey": ""
}
60 changes: 60 additions & 0 deletions app/css/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
html,
body {
padding: 0;
margin: 0;
}

body {
font-family: -apple-system, 'Helvetica Neue', Helvetica, sans-serif;
}

.center-text {
text-align: center;
}

.black {
color: black;
}

.white {
color: white;
}

.player-list {
list-style: none;
}

.player-item {
display: inline;
}

.small {
width: 32px;
height: 32px;
}
.xsmall {
width: 16px;
height: 16px;
}

.medium {
width: 64px;
height: 64px;
}

.large {
width: 128px;
height: 128px;
}

#settings {

}

#browse-button {
width: 20%;
}

#browse-text {
width: 75%;
}
9 changes: 9 additions & 0 deletions app/css/photon.min.css

Large diffs are not rendered by default.

Binary file added app/fonts/photon-entypo.eot
Binary file not shown.
295 changes: 295 additions & 0 deletions app/fonts/photon-entypo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/fonts/photon-entypo.ttf
Binary file not shown.
Binary file added app/fonts/photon-entypo.woff
Binary file not shown.
146 changes: 146 additions & 0 deletions app/gmr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
'use strict'
let request = require('request')
let async = require('async')
let JSONbig = require('json-bigint');
let _ = require('lodash')
let EventEmitter = require('events').EventEmitter
let util = require('util')
let fs = require('fs')
let Config = require('./config/gmr.json')

module.exports = GMR

util.inherits(GMR, EventEmitter)

let host = 'http://multiplayerrobot.com/api/Diplomacy/'

function GMR () {
let self = this

this.authKey = Config.authKey
this.saveFile = Config.saveFile

this.playerId
this.games
this.players

this.authenticateUser = function (authKey, callback) {
let uri = `${host}AuthenticateUser?authKey=${self.authKey}`
return request.get(uri, {timeout: 1000}, (err, res, body) => {
if (err) return callback(err)
return callback(null, body)
})
}

this.getGamesAndPlayers = function (playerIds, authKey, callback) {
if (false === _.isArray(playerIds)) {
playerIds = [playerIds]
}
let uri = `${host}GetGamesAndPlayers?playerIDText=${playerIds.join('_')}&authKey=${self.authKey}`
return request.get(uri, {timeout: 5000}, (err, res, body) => {
if (err) return callback(err)
return callback(null, body)
})
}

}


GMR.prototype.fetchInfo = function (callback) {
let self = this
return async.series([
function auth (callback) {
self.authenticateUser(self.authKey, (err, id) => {
if (err) return callback (err)
self.playerId = id
return callback(null)
})
},
function getGames (callback) {
self.getGamesAndPlayers(self.playerId, self.authKey, (err, gamesAndPlayers) => {
if (err) return callback (err)
self.games = JSONbig.parse(gamesAndPlayers).Games
_.forEach(self.games, game => {
game.CurrentTurn.UserId = game.CurrentTurn.UserId.toString()
_.forEach(game.Players, player => {
player.UserId = player.UserId.toString()
// Normalize TurnOrder such that current player's turn order is 0, second is 1, etc.
player.TurnOrder = (player.TurnOrder - game.CurrentTurn.PlayerNumber + game.Players.length ) % game.Players.length
})
})

return callback(null)
})
},
function getPlayers (callback) {
let playerIds = _(self.games).pluck('Players').flatten()
.pluck('UserId').unique().filter(n => n !== 0)
.value()
self.getGamesAndPlayers(playerIds, self.authKey, (err, gamesAndPlayers) => {
if (err) return callback (err)

self.players = _.reduce(JSONbig.parse(gamesAndPlayers).Players, (ps, p) => {
p.SteamID = p.SteamID.toString()
p.AvatarUrl = p.AvatarUrl.split('.jpg')[0]+'_full.jpg' // better picture
ps[p.SteamID] = p
return ps
}, {})
return callback(null)
})
}
], (err) => {
if (err) return callback(err)
return callback(null, {
players: self.players,
games: self.games
})
})
}

GMR.prototype.getPlayerId = function () {
console.log(this.playerId)
return this.playerId
}

GMR.prototype.getPlayers = function () {
console.log(this.players)
return this.players
}

GMR.prototype.getGames = function () {
console.log(this.games)
return this.games
}

GMR.prototype.getGameSave = function (gameId, callback) {
let uri = `${host}GetLatestSaveFileBytes?authKey=${this.authKey}&gameId=${gameId}`

return request(uri).pipe(fs.createWriteStream(this.saveFile))
.on('error', (err) => callback(err))
.on('finish', callback)
}

GMR.prototype.uploadGameSave = function (turnId, callback) {
let uri = `${host}SubmitTurn?authKey=${this.authKey}&turnId=${turnId}`
return fs.createReadStream(this.saveFile)
.pipe(request.post(uri))
.on('error', (err) => callback(err))
.on('response', function(response) {
console.log(response.statusCode)
console.log(response)
})
.on('end', callback)
}

GMR.prototype.getSettings = function () {
return {
saveFile: this.saveFile,
authKey: this.authKey
}
}

GMR.prototype.setSettings = function (settings) {
this.saveFile = settings.saveFile
this.authKey = settings.authKey
return fs.writeFileSync(__dirname + '/config/gmr.json', JSON.stringify(settings, null, 2))
}
96 changes: 96 additions & 0 deletions app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<!doctype html>
<html ng-app="eGMR">
<head>
<meta charset="utf-8">
<title>GMR Client</title>
<link rel="stylesheet" href="css/index.css">
<link rel="stylesheet" href="css/photon.min.css">
<script type="text/javascript">
require('./js/index.js');
</script>
</head>
<body>
<div ng-controller = "GlobalController as globalCtrl" class="window">
<div class="window-content">
<div class="pane-group">
<div ng-controller = "GameListController as gamesCtrl" class="pane-sm sidebar">
<ul class="list-group">
<li class="list-group-header">
<input class="form-control" ng-model="search" type="text" placeholder="Search for a game">
</li>
<li class="list-group-header">
<h4>My turn</h4>
</li>
<li ng-repeat="game in games|filter:{Name: search, CurrentTurn: {UserId: playerId}}" ng-click="setSelectedGame(game)" ng-class="{active: game.GameId === selectedGame.GameId}" class="list-group-item">
<img class="small img-circle media-object pull-left" ng-src="{{players[game.CurrentTurn.UserId].AvatarUrl}}">
<div class="media-body">
<h5>{{game.Name}}</h5>
<p>
<img ng-repeat="player in game.Players | filter:filterPlayers(game) | orderBy:'TurnOrder'" class="xsmall img-circle media-object pull-left" ng-src="{{players[player.UserId].AvatarUrl}}">
</p>
</div>
</li>
<li class="list-group-header">
<h4>Other games</h4>
</li>
<li ng-repeat="game in games|filter:{Name: search, CurrentTurn: {UserId: '!'+playerId}}" ng-click="setSelectedGame(game)" ng-class="{active: game.GameId === selectedGame.GameId && !isSettingsSelected}" class="list-group-item">
<img class="small img-circle media-object pull-left" ng-src="{{players[game.CurrentTurn.UserId].AvatarUrl}}">
<div class="media-body">
<h5>{{game.Name}}</h5>
<p>
<img ng-repeat="player in game.Players | filter:filterPlayers(game) | orderBy:'TurnOrder'" class="xsmall img-circle media-object pull-left" ng-src="{{players[player.UserId].AvatarUrl}}">
</p>
</div>
</li>
<li id="settings" ng-click="showSettings()" class="list-group-item" ng-class="{active: isSettingsSelected}">
<h4><span class="icon icon-cog"></span>Settings</h4>
</li>
</ul>
</div>
<div class="pane" ng-hide="isSettingsSelected" ng-controller = "GameInfoController as gameCtrl">
<h1 class="center-text">{{selectedGame.Name}}</h1>
<div class="center-text">
<img class="large img-circle media-object" ng-src="{{players[selectedGame.CurrentTurn.UserId].AvatarUrl}}">
<div class="center-text">
<button ng-show="selectedGame.CurrentTurn.UserId===playerId" ng-click="downloadSave()" class="btn btn-large btn-default"><i class="black icon icon-down-circled"></i>Download</button>
<button ng-show="selectedGame.CurrentTurn.UserId===playerId" ng-click="uploadSave()"class="btn btn-large btn-primary"><i class="white icon icon-up-circled"> </i> Upload</button>
</div>
<div ng-show="downloaded">Game has save been downloaded</div>
<div ng-show="uploaded">Game has save been uploaded</div>
</div>
<div>
<h3 class="center-text">{{timeRemaining}} remaining</h3>
</div>
<div class="center-text">
<ul class="player-list">
<li ng-repeat="player in selectedGame.Players | filter: filterPlayers | orderBy:'TurnOrder'" class="player-item">
<img class="medium img-circle media-object" ng-src="{{players[player.UserId].AvatarUrl}}">
</li>
</ul>
</div>
<div ng-show="error" class="center-text">
An error occured: {{error}}
</div>
</div>
<div class="pane" ng-show="isSettingsSelected" ng-controller="SettingsController as settingsCtrl">
<form>
<div class="form-group">
<label>Authentication Key</label>
<input ng-model="settings.authKey" class="form-control" placeholder="I42D4242N7DI">
</div>
<div class="form-group">
<label>Hotseat Save Folder</label>
<input id="browse-text" ng-model="settings.saveFile" class="form-control" placeholder="/Users/D/T/C">
<button ng-click="changeSaveFile()" id="browse-button" class="btn btn-form btn-default">Browse</button>
</div>
<div class="form-actions">
<button type="submit" ng-click="cancelSettings()" class="btn btn-form btn-default">Cancel</button>
<button type="submit" ng-click="saveSettings()" class="btn btn-form btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
Loading

0 comments on commit eed0ce0

Please sign in to comment.