From afe602c9db71b9512e38035faf44423d2567e52e Mon Sep 17 00:00:00 2001 From: Simon Wachter Date: Tue, 8 Jul 2014 19:23:41 +0200 Subject: [PATCH 1/3] Adds a score sheet module, spreadsheet-style Auto-sum columns, dynamic number of players. --- cache.manifest | 4 ++- css/style.css | 11 ++++++ index.html | 5 +++ js/main.js | 6 +++- js/scores.service.js | 81 +++++++++++++++++++++++++++++++++++++++++++ templates/scores.html | 23 ++++++++++++ 6 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 js/scores.service.js create mode 100644 templates/scores.html diff --git a/cache.manifest b/cache.manifest index 9a2d1e0..352dca8 100644 --- a/cache.manifest +++ b/cache.manifest @@ -1,5 +1,5 @@ CACHE MANIFEST -# 2014-4-24 11:13:00 +# 2014-07-05 17:48:00 CACHE: index.html @@ -9,6 +9,7 @@ templates/chronos.html templates/countdown.html templates/counters.html templates/versus.html +templates/scores.html sound/gong.ogg sound/gong.mp3 js/angular.js @@ -17,6 +18,7 @@ js/main.js js/misc.service.js js/timer.service.js js/versus.service.js +js/scores.service.js js/ui-bootstrap-tpls-0.10.0.js js/html5shiv.js js/respond.min.js diff --git a/css/style.css b/css/style.css index b80ecbe..181db5b 100644 --- a/css/style.css +++ b/css/style.css @@ -64,6 +64,17 @@ caption input { padding-right:1ex; } +.player .counter-name { + width: 100%; +} + +.player .score { + text-align: center; + font-size: 1.4em; + font-weight: bold; + display: block; +} + footer { margin-top:1em; } diff --git a/index.html b/index.html index 5f6e577..6419d9d 100644 --- a/index.html +++ b/index.html @@ -47,6 +47,10 @@
+ + +
+
@@ -64,6 +68,7 @@ + diff --git a/js/main.js b/js/main.js index c8f5ede..d51f0f4 100644 --- a/js/main.js +++ b/js/main.js @@ -106,17 +106,21 @@ counterApp.directive('ngReallyClick', [function() { /** * Project entry point. */ -counterApp.controller('TabsCtrl', function($scope, countersService, timersService, versusService, $document, configurationService) { +counterApp.controller('TabsCtrl', function($scope, countersService, timersService, versusService, scoresService, $document, configurationService) { $scope.counters = countersService; $scope.timers = timersService.makeTimers("Count down"); $scope.chronos = timersService.makeTimers("Chrono"); + $scope.players = scoresService.makeScoresheet("Player"); $scope.versus = versusService; $scope.config = configurationService; $scope.counters.add(); $scope.timers.add(); $scope.chronos.add(); + $scope.players.add(); + $scope.players.add(); + $scope.players.newTurn(); $scope.tab = "countdown"; $scope.selectTab = function(name){$scope.tab = name;}; diff --git a/js/scores.service.js b/js/scores.service.js new file mode 100644 index 0000000..00eb0f8 --- /dev/null +++ b/js/scores.service.js @@ -0,0 +1,81 @@ + +counterApp.factory('scoresService', function () { + + var service = {}; + + /* Scoresheet factory */ + service.makeScoresheet = function (name) { + var players = {}; + + players.list = []; + players.total_created = 0; + players.turn_count = 0; + + /* Remove a player */ + players.remove = function (i) { + players.list.remove(i); + }; + + /* Bring a new player to the game */ + players.add = function () { + players.total_created += 1; + players.list.push(players.createPlayer()); + }; + + players.newTurn = function () { + players.turn_count++; + for (var i = 0; i < players.list.length; i++) { + players.list[i].scores.push(''); + } + }; + + players.createPlayer = function () { + var initscores = []; + + for (var i = 0; i < players.turn_count; i++) + initscores.push(''); + + var player = { + "name": name + " " + players.total_created, + "scores": initscores, + + "_total": function () { + var sum = 0; + for (var i = 0; i < player.scores.length; i++) { + sum += +player.scores[i]; + } + + return sum; + } + }; + + + /* Define properties for total + * in a browser compatible way. + */ + /* __defineGetter__ is deprecated */ + if ('__defineGetter__' in player) { + player.__defineGetter__("total", function () { + return player._total(); + }); + } else { + Object.defineProperty(player, "total", { + writable: false, + enumerable: true, + get: function () { + return player._total(); + } + }); + } + + return player; + + }; + + return players; + + }; + + return service; + +}); \ No newline at end of file diff --git a/templates/scores.html b/templates/scores.html new file mode 100644 index 0000000..c13387a --- /dev/null +++ b/templates/scores.html @@ -0,0 +1,23 @@ +
+
+ + + + {{ player.total }} + + +
+
+ + From 5096572699b0933524fb743ece966481756c6814 Mon Sep 17 00:00:00 2001 From: Simon Wachter Date: Thu, 10 Jul 2014 23:31:16 +0200 Subject: [PATCH 2/3] Improved UI --- css/style.css | 18 ++++++++++++++++++ index.html | 39 ++++++++++++++++++--------------------- js/main.js | 6 ++++++ templates/scores.html | 24 ++++++++++++++++-------- 4 files changed, 58 insertions(+), 29 deletions(-) diff --git a/css/style.css b/css/style.css index 181db5b..1f29bd3 100644 --- a/css/style.css +++ b/css/style.css @@ -64,6 +64,24 @@ caption input { padding-right:1ex; } +.row-lg { + overflow-x: auto; + overflow-y: hidden; + white-space: nowrap; +} + +.row-lg [class*="col-lg"], +.row-lg [class*="col-md"], +.row-lg [class*="col-sm"] { + float: none; + display: inline-block; +} + +.player { + padding: 0; + margin: 0; +} + .player .counter-name { width: 100%; } diff --git a/index.html b/index.html index 6419d9d..1a5fc9e 100644 --- a/index.html +++ b/index.html @@ -1,37 +1,34 @@ - - - - - + + + + + - - + + - - All that counts - Countdown, chrono, timers and counters for games or sports - + + All that counts - Countdown, chrono, timers and counters for games or sports + - + - - - - - + + + +
-
-
diff --git a/js/main.js b/js/main.js index d51f0f4..ef3e055 100644 --- a/js/main.js +++ b/js/main.js @@ -103,6 +103,8 @@ counterApp.directive('ngReallyClick', [function() { }; }]); + + /** * Project entry point. */ @@ -125,6 +127,10 @@ counterApp.controller('TabsCtrl', function($scope, countersService, timersServic $scope.tab = "countdown"; $scope.selectTab = function(name){$scope.tab = name;}; + $scope.floor = Math.floor; + $scope.max = Math.max; + $scope.min = Math.min; + /* I don't know where to put this. diff --git a/templates/scores.html b/templates/scores.html index c13387a..4636343 100644 --- a/templates/scores.html +++ b/templates/scores.html @@ -1,23 +1,31 @@ -
-
+
+
- + {{ player.total }} + ng-really-message="Really DELETE this player?" + ng-really-click="players.remove($index)" + class="btn btn-danger btn-small center-block">×
- -
From 82f8540d263ee6e60acea2a40fb671a869815696 Mon Sep 17 00:00:00 2001 From: Simon Wachter Date: Fri, 11 Jul 2014 00:37:49 +0200 Subject: [PATCH 3/3] Adds ranking, match mode, and compute mode (+/-) --- cache.manifest | 2 +- css/style.css | 34 +++++++++++++- js/scores.service.js | 102 +++++++++++++++++++++++++++++++++++++++--- templates/scores.html | 41 +++++++++++++++-- 4 files changed, 167 insertions(+), 12 deletions(-) diff --git a/cache.manifest b/cache.manifest index 352dca8..ee02c4a 100644 --- a/cache.manifest +++ b/cache.manifest @@ -1,5 +1,5 @@ CACHE MANIFEST -# 2014-07-05 17:48:00 +# 2014-07-11 00:41:00 CACHE: index.html diff --git a/css/style.css b/css/style.css index 1f29bd3..1298a3c 100644 --- a/css/style.css +++ b/css/style.css @@ -82,6 +82,16 @@ caption input { margin: 0; } +.player.won { + background-color: #DFF0D8; + border: 1px solid #D6E9C6; +} + +.player.lost { + background-color: #F2DEDE; + border: 1px solid #EBCCD1; +} + .player .counter-name { width: 100%; } @@ -93,6 +103,28 @@ caption input { display: block; } +.player.won .score { + color: #3C763D; +} + +.player.lost .score { + color: #A94442; +} + +.player.won input.form-control { + color: #3C763D; + border-color: #3C763D; +} + +.player.lost input.form-control { + color: #A94442; + border-color: #A94442; +} + +input.form-control.init-score { + background-color: #ededed; +} + footer { margin-top:1em; } @@ -109,7 +141,7 @@ input[type='number'] { -moz-appearance:textfield; } -input::-webkit-outer-spin-button, +input::-webkit-outer-spin-button input::-webkit-inner-spin-button { -webkit-appearance: none; } diff --git a/js/scores.service.js b/js/scores.service.js index 00eb0f8..48605a3 100644 --- a/js/scores.service.js +++ b/js/scores.service.js @@ -10,6 +10,9 @@ counterApp.factory('scoresService', function () { players.list = []; players.total_created = 0; players.turn_count = 0; + players.goal = 100; + players.match = 'off'; + players.mode = 'add' /* Remove a player */ players.remove = function (i) { @@ -29,6 +32,43 @@ counterApp.factory('scoresService', function () { } }; + players.rank = function (index) { + var over = 0; + var under = 0; + var equal = 0; + + var ref = players.list[index].total; + + /* Count those over and under the ref player */ + for (var i=0; i < players.list.length; i++) { + if (i == index) continue; + + var score = players.list[i].total; + + if (score < ref) under += 1; + else if (score > ref) over += 1; + else equal += 1; + } + + /* Depending on the mode and the match, we consider scores above or under the ref to + * make up the rank + */ + var rank; + if ((players.mode == 'add' && (players.match == 'win' || players.match == 'off')) || + (players.mode == 'substract' && players.match == 'lose')) + rank = over + 1; + else if ((players.mode == 'add' && players.match == 'lose') || + (players.mode == 'substract' && (players.match == 'win' || players.match == 'off'))) + rank = under + 1 + + // Get ordinal + // From: https://github.com/jdpedrie/angularjs-ordinal-filter + var s = ["th", "st", "nd", "rd"]; + var v = rank % 100; + + return (equal > 0 ? 'equal ' : '') + rank + ( s[(v - 20) % 10] || s[v] || s[0]); + }; + players.createPlayer = function () { var initscores = []; @@ -39,10 +79,40 @@ counterApp.factory('scoresService', function () { "name": name + " " + players.total_created, "scores": initscores, + /** Check if the player lost **/ + "_lost": function () { + if (players.match == 'win') { + return false; + } else if (players.match == 'lose') { + return player._total() >= players.goal; + } + }, + + /** Check if the player won **/ + "_won": function () { + if (players.match == 'win') { + return player._total() >= players.goal; + } else if (players.match == 'lose') { + return false; + } + }, + + /** Get the player's score **/ "_total": function () { var sum = 0; - for (var i = 0; i < player.scores.length; i++) { - sum += +player.scores[i]; + + // In adding mode, just sum the scores + if (players.mode == 'add') { + for (var i = 0; i < player.scores.length; i++) { + sum += +player.scores[i]; + } + + // In substract mode, substract all scores from the first + } else if (players.mode == 'substract') { + sum = player.scores[0] || 0; + for (var i = 1; i < player.scores.length; i++) { + sum -= +player.scores[i]; + } } return sum; @@ -58,13 +128,31 @@ counterApp.factory('scoresService', function () { player.__defineGetter__("total", function () { return player._total(); }); + player.__defineGetter__("won", function () { + return player._won(); + }); + player.__defineGetter__("lost", function () { + return player._lost(); + }); } else { Object.defineProperty(player, "total", { - writable: false, - enumerable: true, - get: function () { - return player._total(); - } + writable: false, + enumerable: true, + get: function () { + return player._total(); + } + }); + Object.defineProperty(player, "won", { + writable: false, + get: function () { + return player._won(); + } + }); + Object.defineProperty(player, "lost", { + writable: false, + get: function () { + return player._lost(); + } }); } diff --git a/templates/scores.html b/templates/scores.html index 4636343..058629d 100644 --- a/templates/scores.html +++ b/templates/scores.html @@ -1,6 +1,39 @@ -
+
+
+ + + + + +
+
+
+ at + +
+
+
+ + + + +
+
+ +
@@ -8,9 +41,11 @@ ng-repeat="turn in player.scores track by $index" ng-model="player.scores[$index]" ng-init="playerno = $index" + ng-class="{'init-score': players.mode == 'substract' && $index == 0}" tabindex="{{ tabcount + playerno * ($index + 1)}}" /> {{ player.total }} +

{{ players.rank($index) }}