diff --git a/lg/members_en.txt b/lg/members_en.txt index 7003344ddc0ee2de334e994994a7a91decccdcb1..b29593eff33df15a945d8300e7be69bc91a3bcc6 100755 --- a/lg/members_en.txt +++ b/lg/members_en.txt @@ -5,6 +5,7 @@ SORT_LAST_RENEWAL last renewal time SORT_BY_OLDEST_SIG oldest sig time SORT_BY_LAST_SIG last sig time SORT_BY_CENTRALITY centrality degree +SORT_BY_QUALITY member quality SORT_BY_SIG_COUNT certifications count ORDER_BY in the following order ASC ascending @@ -35,6 +36,7 @@ MEMBERS_REACHED members reached SENTRY_CERT sentry certification MEMBER_CERT member certification MEAN_QUALITY mean quality +PROPORTION_MEMBERS_WITH_QUALITY_UPPER_1 Proportion of members with an upper quality an equal in 1 CURRENT_BLOCKCHAIN_TIME Current blockchain time TABLE_TITLE Members that will expire in less than DAYS days diff --git a/lg/members_fr.txt b/lg/members_fr.txt index ffa3aad18f834ead377b30267b105830c6e38bb7..0d2031ee8410378de7035120bbe922323505f65d 100755 --- a/lg/members_fr.txt +++ b/lg/members_fr.txt @@ -5,6 +5,7 @@ SORT_LAST_RENEWAL date de dernier renouvellement SORT_BY_OLDEST_SIG date de plus vielle certification SORT_BY_LAST_SIG date de plus récente certification SORT_BY_CENTRALITY degré de centralité +SORT_BY_QUALITY qualité du membre SORT_BY_SIG_COUNT nombre de certifications reçues ORDER_BY dans l'ordre ASC croissant @@ -35,6 +36,7 @@ MEMBERS_REACHED membres joiniables SENTRY_CERT certification d'un membre référent SENTRIES_REACHED membres référents joiniables MEAN_QUALITY Qualité moyenne +PROPORTION_MEMBERS_WITH_QUALITY_UPPER_1 Proportion de membre avec une qualité >= 1 CURRENT_BLOCKCHAIN_TIME Temps Blockchain actuel TABLE_TITLE Membres dont le statut de membre va expirer dans moins de DAYS jours diff --git a/lib/updateCache.js b/lib/updateCache.js index 0b8dbf410c8716b161aded21c1d9db2d51a51404..96e2370c2c73c0143a21dc1d80b5774127054b1b 100755 --- a/lib/updateCache.js +++ b/lib/updateCache.js @@ -129,7 +129,7 @@ module.exports = (req, res, next) => co(function *() { } // get endBlock - if ( typeof(req.query.end) == 'undefined' || req.query.end < 0) + if ( typeof(req.query.end) == 'undefined' || req.query.end <= 0) { cache.endBlock = yield duniterServer.dal.peerDAL.query('SELECT `hash`,`medianTime`,`number`,`membersCount` FROM block WHERE `fork`=0 ORDER BY `medianTime` DESC LIMIT 1 '); } diff --git a/routes/members.js b/routes/members.js index 0048862136f172e3cdacdd77897120977a7b06b8..bf7f698b2a73cb02f84155d5936221ced5d4327e 100755 --- a/routes/members.js +++ b/routes/members.js @@ -28,6 +28,8 @@ var meanSentriesReachedBySentriesInSingleExtCert = 0; var meanMembersReachedBySentriesInSingleExtCert = 0; var meanSentriesReachedByMembersInSingleExtCert = 0; var meanMembersReachedByMembersInSingleExtCert = 0; +var proportionMembersWithQualityUpper1 = 0; +var proportionMembersWithQualityUpper1IfNoSentries = 0; // wotCentrality cache var lockCentralityCalc = false; @@ -119,6 +121,8 @@ module.exports = (req, res, next) => co(function *() { meanMembersReachedBySentriesInSingleExtCert = 0; meanSentriesReachedByMembersInSingleExtCert = 0; meanMembersReachedByMembersInSingleExtCert = 0; + proportionMembersWithQualityUpper1 = 0; + proportionMembersWithQualityUpper1IfNoSentries = 0; // Réinitialiser le cache des données de centralité if (centrality=='yes') @@ -182,11 +186,24 @@ module.exports = (req, res, next) => co(function *() { let tmpWot1 = wotbInstance.memCopy(); let detailedDistance = tmpWot.detailedDistance(membersList[m].wotb_id, dSen, conf.stepMax, conf.xpercent); membersNbSentriesUnreached[membersList[m].uid] = parseInt(detailedDistance.nbSentries)-parseInt(detailedDistance.nbSuccess); - //console.log("membersNbSentriesUnreached[%s] = %s", membersList[m].uid, membersNbSentriesUnreached[membersList[m].uid]); - // Mesurer la qualité externe du membre courant + // Récupérer les informations détaillés de distance pour une nouvelle identité qui ne serait certifiée que par le membre courant (ce qui équivaut à récupérer les informations de distance pour le membre courant en décrémentant stepMax de 1) let detailedDistanceQualityExt = tmpWot.detailedDistance(membersList[m].wotb_id, dSen, conf.stepMax-1, conf.xpercent); + + // Calculer la qualité du membre courant membersQualityExt[membersList[m].uid] = ((detailedDistanceQualityExt.nbSuccess/detailedDistanceQualityExt.nbSentries)/conf.xpercent).toFixed(2); + if (membersQualityExt[membersList[m].uid] >= 1.0) + { + proportionMembersWithQualityUpper1++; + } + + // Calculer la qualité du membre courant s'il n'y avait pas de référents (autrement di si tout les membres était référents) + let membersQualityIfNoSentries = ((detailedDistanceQualityExt.nbReached/membersList.length)/conf.xpercent).toFixed(2); + //console.log("membersQualityIfNoSentries[%s] = %s", membersList[m].uid, membersQualityIfNoSentries); + if (membersQualityIfNoSentries >= 1.0) + { + proportionMembersWithQualityUpper1IfNoSentries++; + } // Calculate meanSentriesReachedBySentriesInSingleExtCert, meanMembersReachedBySentriesInSingleExtCert, meanSentriesReachedByMembersInSingleExtCert and meanMembersReachedByMembersInSingleExtCert if (currentMemberIsSentry) @@ -434,6 +451,13 @@ module.exports = (req, res, next) => co(function *() { } } } + else if (sort_by == "quality") + { + for (const member of membersList) + { + tabSort.push(membersQualityExt[member.uid]); + } + } else if (sort_by == "sigCount") { for (const memberCertifsList of membersCertifsList) @@ -512,6 +536,13 @@ module.exports = (req, res, next) => co(function *() { meanCentrality /= membersCentrality.length; meanShortestsPathLength /= nbShortestsPath; } + + //Calculate proportionMembersWithQualityUpper1 and proportionMembersWithQualityUpper1IfNoSentries + proportionMembersWithQualityUpper1 /= membersList.length; + proportionMembersWithQualityUpper1IfNoSentries /= membersList.length; + + // Dévérouiller le cache members + lockMembers = false; } // Si le client demande la réponse au format JSON =, le faire @@ -552,6 +583,8 @@ module.exports = (req, res, next) => co(function *() { meanMembersReachedBySentriesInSingleExtCert, meanSentriesReachedByMembersInSingleExtCert, meanMembersReachedByMembersInSingleExtCert, + proportionMembersWithQualityUpper1, + proportionMembersWithQualityUpper1IfNoSentries, // centrality cache data lockCentralityCalc, @@ -600,8 +633,6 @@ module.exports = (req, res, next) => co(function *() { // } } - // Dévérouiller le cache members - lockMembers = false; next() } } catch (e) { diff --git a/routes/membersCount.js b/routes/membersCount.js index d629ea490cbdab95592dc20a974a14d501b5f98b..5f5f0c83ee0bec455244bfdf863dc434c79ced4d 100755 --- a/routes/membersCount.js +++ b/routes/membersCount.js @@ -16,7 +16,7 @@ module.exports = (req, res, next) => co(function *() { var pow = req.query.pow || 'no'; // get lg file - const LANG = getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`); + const LANG = getLang(`${__dirname}/../lg/membersCount_${req.query.lg||'fr'}.txt`); // // get medianTime of beginBlock var beginBlock = yield duniterServer.dal.peerDAL.query('SELECT `medianTime`,`hash` FROM block WHERE `fork`=0 AND `number` = '+cache.beginBlock[0].number+' LIMIT 1'); @@ -63,11 +63,40 @@ module.exports = (req, res, next) => co(function *() { // If achieve next step if ( (cache.stepUnit == "blocks" && bStep == cache.step) || (cache.stepUnit != "blocks" && blockchain[b].medianTime >= nextStepTime)) { + let previousDateTime = ""; + if(tabMembersCount.length > 0) + { + previousDateTime = timestampToDatetime(tabMembersCount[tabMembersCount.length-1].timestamp, cache.onlyDate); + } + else + { + previousDateTime = timestampToDatetime(blockchain[0].medianTime); + } + let dateTime = ""; + if (cache.stepUnit != "blocks") + { + if (cache.step > 1) + { + switch (cache.stepUnit) + { + case "hours": dateTime = previousDateTime+" - "+timestampToDatetime(blockchain[b].medianTime, cache.onlyDate); break; + case "days": dateTime = previousDateTime+" - "+timestampToDatetime(blockchain[b].medianTime-(cache.stepTime/cache.step), cache.onlyDate); break; + case "weeks": dateTime = previousDateTime+" - "+timestampToDatetime(blockchain[b].medianTime, cache.onlyDate); break; + case "months": dateTime = previousDateTime+" - "+timestampToDatetime(blockchain[b].medianTime, cache.onlyDate); break; + case "years": dateTime = previousDateTime+" - "+timestampToDatetime(blockchain[b].medianTime, cache.onlyDate); break; + } + } + else + { + dateTime = previousDateTime; + } + } + // push tabMembersCount tabMembersCount.push({ blockNumber: blockchain[b].number, timestamp: blockchain[b].medianTime, - dateTime: timestampToDatetime(blockchain[b].medianTime, cache.onlyDate), + dateTime: dateTime, membersCount: blockchain[b].membersCount, sentriesCount: cache.blockchain[cacheIndex].sentries, issuersCount: parseInt(stepIssuerCount/bStep), @@ -81,16 +110,22 @@ module.exports = (req, res, next) => co(function *() { } } - // Add current block data - tabMembersCount.push({ - blockNumber: blockchain[blockchain.length-1].number, - timestamp: blockchain[blockchain.length-1].medianTime, - dateTime: LANG['LAST_BLOCK'], - membersCount: blockchain[blockchain.length-1].membersCount, - sentriesCount: cache.blockchain[cache.blockchain.length-1].sentries, - issuersCount: blockchain[blockchain.length-1].issuersCount, - powMin: blockchain[blockchain.length-1].powMin - }); + // Add current block data (only if end parameter is undefined or negative) + if (typeof(req.query.end) == 'undefined' || req.query.end <= 0) + { + tabMembersCount.push({ + blockNumber: blockchain[blockchain.length-1].number, + timestamp: blockchain[blockchain.length-1].medianTime, + dateTime: LANG['LAST_BLOCK'], + membersCount: blockchain[blockchain.length-1].membersCount, + sentriesCount: cache.blockchain[cache.blockchain.length-1].sentries, + issuersCount: blockchain[blockchain.length-1].issuersCount, + powMin: blockchain[blockchain.length-1].powMin + }); + } + + // Delete first tabMembersCount cell + tabMembersCount.splice(0, 1); if (format == 'JSON') res.status(200).jsonp( tabMembersCount ) @@ -143,7 +178,7 @@ module.exports = (req, res, next) => co(function *() { tabMembersCount, begin: cache.beginBlock[0].number, end: cache.endBlock[0].number, - form: `${LANG["BEGIN"]} #<input type="number" name="begin" value="${cache.beginBlock[0].number}" min="0"> - ${LANG["END"]} #<input type="number" name="end" value="${cache.endBlock[0].number}" min="1"> - ${LANG["STEP"]} <input type="number" name="step" value="${cache.step}" min="1"> + form: `${LANG["BEGIN"]} #<input type="number" name="begin" value="${cache.beginBlock[0].number}" min="0"> - ${LANG["END"]} #<input type="number" name="end" value="${cache.endBlock[0].number}" > - ${LANG["STEP"]} <input type="number" name="step" value="${cache.step}" min="1"> <select name="stepUnit"> <option name="stepUnit" value ="blocks"${cache.stepUnit == 'blocks' ? 'selected' : ''}>${LANG["BLOCKS"]} <option name="stepUnit" value ="hours"${cache.stepUnit == 'hours' ? 'selected' : ''}>${LANG["HOURS"]} @@ -157,7 +192,7 @@ module.exports = (req, res, next) => co(function *() { chart: { type: 'line', data: { - labels: tabMembersCount.map(item=>item.dateTime), + labels: (cache.stepUnit == "blocks") ? tabMembersCount.map(item=>item.blockNumber):tabMembersCount.map(item=>item.dateTime), datasets: datasets, }, options: { diff --git a/views/members.html b/views/members.html index a2a9d77be898b45eb653421ae1a1366e201f41b4..02ab744e1ee695380a153f6a0511374639a1cf90 100755 --- a/views/members.html +++ b/views/members.html @@ -32,6 +32,7 @@ ${(host.substr(host.length-6,6) == '.onion') ? HTML_TOR_HEAD:HTML_HEAD} <option name="sort_by" value ="oldestSig" ${sort_by == 'oldestSig' ? 'selected' : ''}>${LANG["SORT_BY_OLDEST_SIG"]} <option name="sort_by" value ="lastSig" ${sort_by == 'lastSig' ? 'selected' : ''}>${LANG["SORT_BY_LAST_SIG"]} <option name="sort_by" value ="centrality" ${sort_by == 'centrality' ? 'selected' : ''}>${LANG["SORT_BY_CENTRALITY"]} +<option name="sort_by" value ="quality" ${sort_by == 'quality' ? 'selected' : ''}>${LANG["SORT_BY_QUALITY"]} <option name="sort_by" value ="sigCount" ${sort_by == 'sigCount' ? 'selected' : ''}>${LANG["SORT_BY_SIG_COUNT"]} </select> ${LANG["ORDER_BY"]} <select name="order"> <option name="order" value ="asc"> ${LANG["ASC"]} @@ -81,6 +82,7 @@ ${(membersLastCentralityCalcTime==0) ? ` <tr><td align='center'>${LANG["SENTRY_CERT"]}</td><td align='center'>${meanSentriesReachedBySentriesInSingleExtCert}%</td><td align='center'>${meanMembersReachedBySentriesInSingleExtCert}%</td></tr> <tr><td align='center'>${LANG["MEMBER_CERT"]}</td><td align='center'><font color="${(meanSentriesReachedByMembersInSingleExtCert<xpercent) ? 'DarkRed' : 'blue' }"><b>${meanSentriesReachedByMembersInSingleExtCert}%</b></font></td><td align='center'><b>${meanMembersReachedByMembersInSingleExtCert}%</b></td></tr> <tr><td align='center'><b>${LANG["MEAN_QUALITY"]}</b></td><td align='center'><font color="red"><b>${(meanSentriesReachedByMembersInSingleExtCert/(xpercent*100)).toFixed(2)}</b></font></td><td align='center'><b>${(meanMembersReachedByMembersInSingleExtCert/(xpercent*100)).toFixed(2)}</b></td></tr> + <tr><td align='center'><b>${LANG["PROPORTION_MEMBERS_WITH_QUALITY_UPPER_1"]}</b></td><td align='center'><font color="red"><b>${(proportionMembersWithQualityUpper1*100).toFixed(2)}%</b></font></td><td align='center'><b>${(proportionMembersWithQualityUpper1IfNoSentries*100).toFixed(2)}%</b></td></tr> </table> <br>