Xp history

This commit is contained in:
Garry Newman committed 2016-02-29 17:12:24 +00:00
1 parent 9732dafb47
commit 5fa14a3247
7 files changed
+229 -19

No files matched your search

+58 -1
View File
@@ -1,6 +1,63 @@
<div ng-controller="PlayerXpController" flex layout="column" id="PlayerXpController">
Show info about this player xp here
<md-content flex layout-padding>
<h2>Statistics for player <a href="#/player/{{userid}}/">{{userid}}</a></h2>
<div layout="row" layout-sm="column">
<div flex>
<md-card>
<md-card-title>
<md-card-title-text>
<span class="md-headline">Xp Income Sources</span>
<span class="md-subhead">Where has this user got their Xp from</span>
</md-card-title-text>
</md-card-title>
<md-card-content layout="row" layout-align="space-between">
<md-card-title-media flex>
<nvd3 flex options="Sources.Options" data="Sources.Data"></nvd3>
</md-card-title-media>
</md-card-content>
</md-card>
</div>
<div flex>
<md-card>
<md-card-title>
<md-card-title-text>
<span class="md-headline">Xp Outgoing Sources</span>
<span class="md-subhead">Where has this user spent their Xp</span>
</md-card-title-text>
</md-card-title>
<md-card-content layout="row" layout-align="space-between">
<md-card-title-media flex>
<nvd3 flex options="Outgoings.Options" data="Outgoings.Data"></nvd3>
</md-card-title-media>
</md-card-content>
</md-card>
</div>
</div>
<div flex>
<md-card>
<md-card-title>
<md-card-title-text>
<span class="md-headline">Xp Over Time</span>
<span class="md-subhead">How much XP has this user got over time</span>
</md-card-title-text>
</md-card-title>
<md-card-content layout="row" layout-align="space-between">
<md-card-title-media flex>
<nvd3 flex options="OverTime.Options" data="OverTime.Data"></nvd3>
</md-card-title-media>
</md-card-content>
</md-card>
</div>
</md-content>
</div>
+3 -9
View File
@@ -1,9 +1,7 @@
<div ng-controller="PlayerListController" flex layout="column" id="PlayerListController">
<md-content flex id="vertical-container">
<md-list>
<div ng-repeat="line in Players | filter : FilterText">
<md-list-item class="md-3-line" layout="row" style="min-height: auto;">
<md-list-item class="" ng-repeat="line in Players | filter : FilterText" href="#/player/{{line.SteamID}}/">
<div flex layout="row">
<div flex class="md-list-item-text">
<h3><a href="#/player/{{line.SteamID}}/">{{line.DisplayName}}</a></h3>
@@ -23,7 +21,7 @@
</div>
<div flex="10"style="text-align: right">
XP: {{line.UnspentXp}}
XP: <a href="#/player/{{line.SteamID}}/xp">{{line.UnspentXp}}</a>
</div>
<div flex="20"style="text-align: right">
@@ -36,12 +34,8 @@
{{line.ConnectedSeconds | SecondsToDuration}}
</div>
</md-list-item>
<md-divider></md-divider>
</div>
</md-list-item>
</md-list>
</md-content>
+7 -3
View File
@@ -13,10 +13,10 @@
</head>
<body ng-cloak layout="row" ng-controller="RconController">
<div ng-include="'html/connect.html'" ng-show="!Connected" flex layout="row">
<div ng-include="'html/connect.html'" ng-show="!Connected" flex layout="row" ng-cloak>
</div>
<md-sidenav md-component-id="left" md-is-locked-open="$mdMedia('gt-sm')" class="md-whiteframe-6dp menu" ng-show="Connected">
<md-sidenav md-component-id="left" md-is-locked-open="$mdMedia('gt-sm')" class="md-whiteframe-6dp menu" ng-show="Connected" ng-cloak>
<md-list>
<md-list-item ng-repeat="p in pages | filter: { Nav: '' } ">
@@ -28,7 +28,7 @@
</md-sidenav>
<div layout="column" flex ng-show="Connected">
<div layout="column" flex ng-show="Connected" ng-cloak>
<md-toolbar layout="row">
<div class="md-toolbar-tools">
@@ -62,6 +62,10 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.2/nv.d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-nvd3/1.0.5/angular-nvd3.min.js"></script>
<!-- Data manipulation -->
<script src="js/linq.min.js"></script>
<!-- Our stuff -->
<script src="js/rconService.js"></script>
<script src="js/app.js"></script>
<script src="js/console.js"></script>
+1 -5
View File
@@ -1,6 +1,6 @@
var app = angular.module( 'RconApp', ['ngMaterial', 'ngRoute'] );
var app = angular.module( 'RconApp', ['ngMaterial', 'ngRoute', 'nvd3'] );
app.service( 'rconService', [RconService] );
@@ -30,8 +30,6 @@ function RconController( $scope, $rootScope, rconService, $mdSidenav, $timeout,
return [value];
} );
console.log( $scope.pages );
$scope.OpenLeftMenu = function ()
{
$mdSidenav( 'left' ).toggle();
@@ -89,8 +87,6 @@ function ConnectionController( $scope, rconService )
if ( $scope.PreviousConnects == null )
$scope.PreviousConnects = new Array();
console.log( $scope.PreviousConnects );
$scope.Connect = function ()
{
$scope.LastErrorMessage = null;
+10
View File
@@ -0,0 +1,10 @@
/*--------------------------------------------------------------------------
* linq.js - LINQ for JavaScript
* ver 2.2.0.2 (Jan. 21th, 2011)
*
* created and maintained by neuecc <ils@neue.cc>
* licensed under Microsoft Public License(Ms-PL)
* http://neue.cc/
* http://linqjs.codeplex.com/
*--------------------------------------------------------------------------*/
Enumerable=function(){var m="Single:sequence contains more than one element.",e=true,b=null,a=false,c=function(a){this.GetEnumerator=a};c.Choice=function(){var a=arguments[0]instanceof Array?arguments[0]:arguments;return new c(function(){return new f(g.Blank,function(){return this.Yield(a[Math.floor(Math.random()*a.length)])},g.Blank)})};c.Cycle=function(){var a=arguments[0]instanceof Array?arguments[0]:arguments;return new c(function(){var b=0;return new f(g.Blank,function(){if(b>=a.length)b=0;return this.Yield(a[b++])},g.Blank)})};c.Empty=function(){return new c(function(){return new f(g.Blank,function(){return a},g.Blank)})};c.From=function(j){if(j==b)return c.Empty();if(j instanceof c)return j;if(typeof j==i.Number||typeof j==i.Boolean)return c.Repeat(j,1);if(typeof j==i.String)return new c(function(){var b=0;return new f(g.Blank,function(){return b<j.length?this.Yield(j.charAt(b++)):a},g.Blank)});if(typeof j!=i.Function){if(typeof j.length==i.Number)return new h(j);if(!(j instanceof Object)&&d.IsIEnumerable(j))return new c(function(){var c=e,b;return new f(function(){b=new Enumerator(j)},function(){if(c)c=a;else b.moveNext();return b.atEnd()?a:this.Yield(b.item())},g.Blank)})}return new c(function(){var b=[],c=0;return new f(function(){for(var a in j)!(j[a]instanceof Function)&&b.push({Key:a,Value:j[a]})},function(){return c<b.length?this.Yield(b[c++]):a},g.Blank)})},c.Return=function(a){return c.Repeat(a,1)};c.Matches=function(h,e,d){if(d==b)d="";if(e instanceof RegExp){d+=e.ignoreCase?"i":"";d+=e.multiline?"m":"";e=e.source}if(d.indexOf("g")===-1)d+="g";return new c(function(){var b;return new f(function(){b=new RegExp(e,d)},function(){var c=b.exec(h);return c?this.Yield(c):a},g.Blank)})};c.Range=function(e,d,a){if(a==b)a=1;return c.ToInfinity(e,a).Take(d)};c.RangeDown=function(e,d,a){if(a==b)a=1;return c.ToNegativeInfinity(e,a).Take(d)};c.RangeTo=function(d,e,a){if(a==b)a=1;return d<e?c.ToInfinity(d,a).TakeWhile(function(a){return a<=e}):c.ToNegativeInfinity(d,a).TakeWhile(function(a){return a>=e})};c.Repeat=function(d,a){return a!=b?c.Repeat(d).Take(a):new c(function(){return new f(g.Blank,function(){return this.Yield(d)},g.Blank)})};c.RepeatWithFinalize=function(a,e){a=d.CreateLambda(a);e=d.CreateLambda(e);return new c(function(){var c;return new f(function(){c=a()},function(){return this.Yield(c)},function(){if(c!=b){e(c);c=b}})})};c.Generate=function(a,e){if(e!=b)return c.Generate(a).Take(e);a=d.CreateLambda(a);return new c(function(){return new f(g.Blank,function(){return this.Yield(a())},g.Blank)})};c.ToInfinity=function(d,a){if(d==b)d=0;if(a==b)a=1;return new c(function(){var b;return new f(function(){b=d-a},function(){return this.Yield(b+=a)},g.Blank)})};c.ToNegativeInfinity=function(d,a){if(d==b)d=0;if(a==b)a=1;return new c(function(){var b;return new f(function(){b=d+a},function(){return this.Yield(b-=a)},g.Blank)})};c.Unfold=function(h,b){b=d.CreateLambda(b);return new c(function(){var d=e,c;return new f(g.Blank,function(){if(d){d=a;c=h;return this.Yield(c)}c=b(c);return this.Yield(c)},g.Blank)})};c.prototype={CascadeBreadthFirst:function(g,b){var h=this;g=d.CreateLambda(g);b=d.CreateLambda(b);return new c(function(){var i,k=0,j=[];return new f(function(){i=h.GetEnumerator()},function(){while(e){if(i.MoveNext()){j.push(i.Current());return this.Yield(b(i.Current(),k))}var f=c.From(j).SelectMany(function(a){return g(a)});if(!f.Any())return a;else{k++;j=[];d.Dispose(i);i=f.GetEnumerator()}}},function(){d.Dispose(i)})})},CascadeDepthFirst:function(g,b){var h=this;g=d.CreateLambda(g);b=d.CreateLambda(b);return new c(function(){var j=[],i;return new f(function(){i=h.GetEnumerator()},function(){while(e){if(i.MoveNext()){var f=b(i.Current(),j.length);j.push(i);i=c.From(g(i.Current())).GetEnumerator();return this.Yield(f)}if(j.length<=0)return a;d.Dispose(i);i=j.pop()}},function(){try{d.Dispose(i)}finally{c.From(j).ForEach(function(a){a.Dispose()})}})})},Flatten:function(){var h=this;return new c(function(){var j,i=b;return new f(function(){j=h.GetEnumerator()},function(){while(e){if(i!=b)if(i.MoveNext())return this.Yield(i.Current());else i=b;if(j.MoveNext())if(j.Current()instanceof Array){d.Dispose(i);i=c.From(j.Current()).SelectMany(g.Identity).Flatten().GetEnumerator();continue}else return this.Yield(j.Current());return a}},function(){try{d.Dispose(j)}finally{d.Dispose(i)}})})},Pairwise:function(b){var e=this;b=d.CreateLambda(b);return new c(function(){var c;return new f(function(){c=e.GetEnumerator();c.MoveNext()},function(){var d=c.Current();return c.MoveNext()?this.Yield(b(d,c.Current())):a},function(){d.Dispose(c)})})},Scan:function(i,g,j){if(j!=b)return this.Scan(i,g).Select(j);var h;if(g==b){g=d.CreateLambda(i);h=a}else{g=d.CreateLambda(g);h=e}var k=this;return new c(function(){var b,c,j=e;return new f(function(){b=k.GetEnumerator()},function(){if(j){j=a;if(!h){if(b.MoveNext())return this.Yield(c=b.Current())}else return this.Yield(c=i)}return b.MoveNext()?this.Yield(c=g(c,b.Current()))Line truncated
+142
View File
@@ -1,7 +1,149 @@
app.controller( 'PlayerXpController', PlayerXpController );
function PlayerXpController( $scope, rconService, $routeParams )
{
$scope.userid = $routeParams.userid;
$scope.Sources =
{
Options: {
chart: {
type: "pieChart",
height: 400,
x: function ( d ) { return d.key; },
y: function ( d ) { return d.value; },
showLabels : false
}
}
};
$scope.Outgoings =
{
Options: {
chart: {
type: "pieChart",
height: 400,
x: function ( d ) { return d.key; },
y: function ( d ) { return d.value; },
showLabels: false
}
}
};
$scope.OverTime =
{
Options: {
chart: {
type: "multiBarChart",
height: 700,
stacked: true,
x: function ( d ) { return d[0]; },
y: function ( d ) { return Math.round( d[1] * 10 ) / 10; },
showLabels: false,
xAxis: { showMaxMin: false, tickFormat: function ( d ) { return d3.time.format( '%d %b %H%p' )( new Date( d ) ) } },
yAxis: { tickFormat: function ( d ) { return d3.format( ',.2f' )( d ); } },
clipEdge: true,
useInteractiveGuideline: true,
defined: function(d) { return d[0] != null }
}
}
}
$scope.Refresh = function ()
{
rconService.Request( "xp.history " + $scope.userid, $scope, function ( msg )
{
$scope.History = JSON.parse( msg.Message );
$scope.Sources.Data = Enumerable.From( $scope.History )
.Where( function ( x ) { return x.Amount > 0; } )
.GroupBy( "$.Type", null,
function ( key, g )
{
return {
key: key,
value: g.Sum( "$.Amount" )
}
} )
.ToArray();
$scope.Outgoings.Data = Enumerable.From( $scope.History )
.Where( function ( x ) { return x.Amount < 0; } )
.GroupBy( "$.Type", null,
function ( key, g )
{
return {
key: key,
value: -1 * g.Sum( "$.Amount" )
}
} )
.ToArray();
var Hour = 60 * 60;
$scope.OverTime.Data = FixMissingData( Enumerable.From( $scope.History )
.Where( function ( x ) { return x.Amount > 0; } )
.GroupBy( "$.Type", null,
function ( key, g )
{
return {
key: key,
values: g.GroupBy( function ( x ) { return Math.round( x.Date / Hour ) * Hour; }, null, function ( key, g )
{
return [key * 1000, g.Sum( "$.Amount" )];
} )
.ToArray()
}
} )
.ToArray(), Hour * 1000 );
console.log( $scope.OverTime.Data );
} );
}
rconService.InstallService( $scope, $scope.Refresh )
}
// Fix missing gaps in a range
function FixMissingData( data, series )
{
// Get the range
var min = Enumerable.From( data ).Min( function ( x ) { return Enumerable.From( x.values ).Min( "$[0]" ); } )
var max = Enumerable.From( data ).Max( function ( x ) { return Enumerable.From( x.values ).Max( "$[0]" ); } )
// Fucking Javascript You Cunt
data.forEach( function ( d )
{
var expected = min;
var newData = [];
d.values.forEach( function ( d )
{
while ( d[0] != expected && expected <= max )
{
newData.push( [expected, 0.0] );
expected += series;
}
if ( d[0] == expected )
{
newData.push( d );
expected += series;
}
} );
while ( expected <= max )
{
newData.push( [expected, 0.0] );
expected += series;
}
d.values = newData;
} );
return data;
}
+8 -1
View File
@@ -1,7 +1,7 @@
app.controller( 'PlayerListController', PlayerListController );
function PlayerListController( $scope, rconService )
function PlayerListController( $scope, rconService, $interval )
{
$scope.Output = new Array();
@@ -14,4 +14,11 @@ function PlayerListController( $scope, rconService )
}
rconService.InstallService( $scope, $scope.Refresh )
var timer = $interval( function ()
{
//$scope.Refresh();
}.bind( this ), 1000 );
$scope.$on( '$destroy', function () { $interval.cancel( timer ) } )
}