Skip to content

Commit 708aafd

Browse files
author
_pants
committed
color countries by type of peers online
1 parent 4f0bd8f commit 708aafd

File tree

10 files changed

+99
-26
lines changed

10 files changed

+99
-26
lines changed

app/_css/app.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6915,7 +6915,7 @@ circle.get {
69156915
fill: #ffcc66;
69166916
}
69176917

6918-
path.p2p {
6918+
path.connection {
69196919
fill: none;
69206920
stroke-width: 1;
69216921
stroke: white;

app/js/helpers.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function makeLogger(prefix) {
2424
};
2525
}
2626

27-
//var log = makeLogger('helpers');
27+
var log = makeLogger('helpers');
2828

2929
function randomChoice(collection) {
3030
if (_.isArray(collection)) {
@@ -54,7 +54,12 @@ function deleteByPath(obj, path) {
5454
path = path.split('.');
5555
var name = path[0], i = 0, l = path.length;
5656
for (; i<l-1 && path[i+1]; ++i) {
57-
obj = obj[name];
57+
try {
58+
obj = obj[name];
59+
} catch(e) {
60+
log('deleteByPath(', obj, path, ') caused', e);
61+
return; // XXX
62+
}
5863
name = path[i+1];
5964
}
6065
if (i == l - 1 && name && obj) { // XXX && obj check necessary?

app/js/services.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,17 @@ angular.module('app.services', [])
154154

155155
function handleSync(msg) {
156156
// XXX use modelValidatorSrvc to validate update before accepting
157-
var data = msg.data, path = data.path, value = data.value;
158-
if (data.delete) {
157+
var data = msg.data, path = data.path, value = data.value, state = data.state;
158+
if (state) {
159+
merge(model, state);
160+
} else if (data.delete) {
159161
deleteByPath(model, path);
160162
} else {
161163
deleteByPath(model, path);
162164
merge(model, value, path);
163165
}
164166
$rootScope.$apply();
165-
log.debug('handleSync applied sync:\npath:', path || '""', '\nvalue:', value, '\ndelete:', data.delete);
167+
//log.debug('handleSync applied sync:\npath:', path || '""', '\nvalue:', value, '\ndelete:', data.delete);
166168
}
167169

168170
syncSubscriptionKey = {chan: MODEL_SYNC_CHANNEL, cb: handleSync};

app/js/vis.js

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ angular.module('app.vis', [])
55
scale: 1400,
66
translate: [500, 350],
77
style: {
8+
giveModeColor: '#00ff80',
9+
getModeColor: '#ffcc66',
10+
countryOpacityMin: 0,
11+
countryOpacityMax: .5,
812
self: {
913
r: 5
1014
},
@@ -76,18 +80,55 @@ function VisCtrl($scope, $window, logFactory, modelSrvc, CONFIG) {
7680
$scope.self = $scope.project(loc);
7781
}, true);
7882

79-
$scope.opacityByCountry = {};
80-
var countryOpacityScale = d3.scale.linear()
81-
.domain([0, 1000])
82-
.range([0, .2])
83-
.clamp(true);
83+
$scope.fillByCountry = {};
84+
var maxGiveGet = 0,
85+
countryOpacityScale = d3.scale.linear()
86+
.range([CONFIG.style.countryOpacityMin, CONFIG.style.countryOpacityMax])
87+
.clamp(true),
88+
countryFillScale = d3.scale.linear(),
89+
GMC = d3.rgb(CONFIG.style.getModeColor),
90+
getModeColorPrefix = 'rgba('+GMC.r+','+GMC.g+','+GMC.b+',',
91+
countryFillInterpolator = d3.interpolateRgb(CONFIG.style.giveModeColor,
92+
CONFIG.style.getModeColor);
93+
94+
function updateFill(country) {
95+
var npeers = getByPath(model, 'countries.'+country+'.npeers.online');
96+
if (!npeers) return;
97+
var censors = getByPath(model, 'countries.'+country).censors,
98+
scaledOpacity = countryOpacityScale(npeers.giveGet),
99+
colorPrefix, fill;
100+
if (_.isNaN(scaledOpacity)) {
101+
log.error('scaledOpacity is NaN');
102+
debugger;
103+
}
104+
if (censors) {
105+
if (npeers.giveGet !== npeers.get) {
106+
log.warn('npeers.giveGet (', npeers.giveGet, ') !== npeers.get (', npeers.get, ') for censoring country', country);
107+
}
108+
colorPrefix = getModeColorPrefix;
109+
} else {
110+
countryFillScale.domain([-npeers.giveGet, npeers.giveGet]);
111+
var scaledFill = countryFillScale(npeers.get - npeers.give),
112+
color = d3.rgb(countryFillInterpolator(scaledFill));
113+
colorPrefix = 'rgba('+color.r+','+color.g+','+color.b+',';
114+
}
115+
fill = colorPrefix+(scaledOpacity||0)+')';
116+
$scope.fillByCountry[country] = fill;
117+
}
84118

85119
var unwatchAllCountries = $scope.$watch('model.countries', function(countries) {
86120
if (!countries) return;
87121
unwatchAllCountries();
88122
_.forEach(countries, function(stats, country) {
89-
$scope.$watch('model.countries.'+country+'.nusers.online', function(nusers) {
90-
$scope.opacityByCountry[country] = countryOpacityScale(nusers) || 0;
123+
$scope.$watch('model.countries.'+country+'.npeers.online', function(npeers) {
124+
if (!npeers) return;
125+
if (npeers.giveGet > maxGiveGet) {
126+
maxGiveGet = npeers.giveGet;
127+
countryOpacityScale.domain([0, maxGiveGet]);
128+
_.forEach(countries, updateFill);
129+
} else {
130+
updateFill(country);
131+
}
91132
});
92133
});
93134
}, true);

app/partials/footer.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
{{ model.settings.email }} ·
1717
{{ model.connectivity.gtalk }} to Google Talk ·
1818
XXX Lantern friends online ·
19-
connected to {{ model.connectivity.peers.lifetime.length }} peers in {{ ncountries || 'XXX' }} countries ·
19+
connected to {{ model.connectivity.peers.current.length }} peers in {{ ncountries || 'XXX' }} countries ·
2020
{{ model.transfers.bpsUp }} M/s up ·
2121
{{ model.transfers.bpsDn }} M/s down ·
22-
{{ model.transfers.bytesTotal || '0B' }} lifetime
22+
{{ model.transfers.bytesTotal || 'XXX M' }} lifetime
2323
</span>
2424
<span ng-hide="model.connectivity.peers.lifetime.length">
2525
{{ model.connectivity.gtalk }} to Google Talk ·

app/partials/vis.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<svg id="vis" ng-controller="VisCtrl" ng-show="model.showVis">
22
<g id="countries">
33
<g ng-repeat="d in countryGeometries">
4-
<title>{{ d.alpha2 | i18n }}: {{ model.countries[d.alpha2].nusers.online || 0 }} users online</title><!-- XXX i18n -->
5-
<path d="{{ countryPaths[d.alpha2] }}" fill="rgba(255, 255, 255, {{ opacityByCountry[d.alpha2] || 0 }})" class="{{ d.alpha2 }}"/>
4+
<title ui-if="d.alpha2">{{ d.alpha2 | i18n }}: {{ model.countries[d.alpha2].npeers.online.giveGet || 0 }} peers online, {{ model.countries[d.alpha2].npeers.online.give || 0 }} in Give Mode, {{ model.countries[d.alpha2].npeers.online.get || 0 }} in Get Mode</title><!-- XXX i18n -->
5+
<path fill="{{ fillByCountry[d.alpha2] || 'rgba(0, 0, 0, 0)' }}" class="{{ d.alpha2 }}" d="{{ countryPaths[d.alpha2] }}"/>
66
</g>
77
</g>
88
<g id="peersCurrent">
99
<g ng-repeat="peer in model.connectivity.peers.current">
10-
<path d="M {{ self.x }} {{ self.y }} Q {{ controlpoint(peer).x }} {{ controlpoint(peer).y }} {{ project(peer).x }} {{ project(peer).y }}" class="p2p"/>
10+
<path d="M {{ self.x }} {{ self.y }} Q {{ controlpoint(peer).x }} {{ controlpoint(peer).y }} {{ project(peer).x }} {{ project(peer).y }}" class="connection"/>
1111
<circle cx="{{ project(peer).x }}" cy="{{ project(peer).y }}" r="{{ peerR }}"
1212
id="{{ peer.peerid }}" class="peer {{ peer.mode }}" filter="url(#blur)">
1313
<title>{{ peer | prettyUser }}</title>

mock/bayeux_backend.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ BayeuxBackend.prototype.resetModel = function() {
3636
merge(this.model, {bayeuxProtocol: BayeuxBackend.VERSION}, 'version.installed');
3737
};
3838

39+
BayeuxBackend.prototype.publishMultiple = function(state) {
40+
if (_.isEmpty(this._clients)) {
41+
//log('[publishSync]', 'no clients to publish to');
42+
return;
43+
}
44+
var data = {state: state};
45+
log('[publishMultiple]\n', data);
46+
this._bayeux._server._engine.publish({channel: MODEL_SYNC_CHANNEL, data: data});
47+
};
48+
3949
BayeuxBackend.prototype.publishSync = function(path, delete_) {
4050
if (_.isEmpty(this._clients)) {
4151
//log('[publishSync]', 'no clients to publish to');
@@ -48,7 +58,7 @@ BayeuxBackend.prototype.publishSync = function(path, delete_) {
4858
} else {
4959
data.value = getByPath(this.model, path);
5060
}
51-
//log('[publishSync]\n', data);
61+
log('[publishSync]\n', data);
5262
this._bayeux._server._engine.publish({channel: MODEL_SYNC_CHANNEL, data: data});
5363
//this._bayeux.getClient().publish({ // XXX why doesn't this work?
5464
};

mock/http_api.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ ApiServlet.prototype.updateModel = function(state, publish) {
109109
}
110110
};
111111

112+
ApiServlet.prototype.updateMultiple = function(state, publish) {
113+
for (var path in state) {
114+
merge(this.model, state[path], path);
115+
}
116+
this._bayeuxBackend.publishMultiple.call(this._bayeuxBackend, state);
117+
};
118+
112119
/*
113120
* Show next modal that should be shown, including possibly MODAL.none.
114121
* Needed because some modals can be skipped if the user is

mock/scenarios.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,21 @@ exports.SCENARIOS = {
363363
func: function() {
364364
var this_ = this;
365365
setInterval(function() {
366-
var randomCountry = randomChoice(this_.model.countries),
367-
stats = this_.model.countries[randomCountry],
368-
nusersOnlineNow = getByPath(stats, 'nusers.online', _.random(0, 1000)),
369-
nusersOnlineNext = Math.max(0, nusersOnlineNow + _.random(-50, 50)),
366+
var country = randomChoice(this_.model.countries),
367+
stats = this_.model.countries[country],
368+
censors = stats.censors,
369+
npeersOnlineGive = getByPath(stats, 'npeers.online.give',
370+
censors ? 0 : _.random(0, 1000)),
371+
npeersOnlineGet = getByPath(stats, 'npeers.online.get',
372+
censors ? _.random(0, 1000) :_.random(0, 500)),
373+
npeersOnlineGive_ = censors ? npeersOnlineGive :
374+
Math.max(0, npeersOnlineGive + _.random(-50, 50)),
375+
npeersOnlineGet_ = Math.max(0, npeersOnlineGet + _.random(-50, 50)),
370376
update = {};
371-
update['countries.'+randomCountry+'.nusers.online'] = nusersOnlineNext;
372-
this_.updateModel(update, true);
377+
update['countries.'+country+'.npeers.online.give'] = npeersOnlineGive_;
378+
update['countries.'+country+'.npeers.online.get'] = npeersOnlineGet_;
379+
update['countries.'+country+'.npeers.online.giveGet'] = npeersOnlineGive_ + npeersOnlineGet_;
380+
this_.updateMultiple(update);
373381
}, 1000);
374382
}
375383
}

sass/_vis.sass

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ circle.give
1212
circle.get
1313
fill: $getModeColor
1414

15-
path.p2p
15+
path.connection
1616
fill: none
1717
stroke-width: 1
1818
stroke: #fff

0 commit comments

Comments
 (0)