Added display of conribution rank statys + acquired badges

pull/3/head
Sami Mokaddem 2017-11-08 15:34:02 +01:00
parent a9d5ca5657
commit 605538ce97
7 changed files with 191 additions and 11 deletions

View File

@ -35,6 +35,11 @@ maxLevel=16
15=32768
16=65536
[rankRequirementsMisc]
heavilyCount=10
recentDays=31
regularlyDays=7
[rankRequirementsText]
1=Contributing via sighting at least once a year
2=Contributing via attributes or objects to events at least once a year

View File

@ -13,8 +13,13 @@ class Contributor_helper:
self.cfg_org_rank.read(os.path.join(os.environ['DASH_CONFIG'], 'ranking.cfg'))
#honorBadge
self.honorBadgeNum = len(self.cfg_org_rank.options('HonorBadge'))
self.heavilyCount = self.cfg_org_rank.getint('rankRequirementsMisc', 'heavilyCount')
self.recentDays = self.cfg_org_rank.getint('rankRequirementsMisc', 'recentDays')
self.regularlyDays = self.cfg_org_rank.getint('rankRequirementsMisc', 'regularlyDays')
self.org_honor_badge_title = {}
for badgeNum in range(1, len(self.cfg_org_rank.options('HonorBadge'))+1): #get Num of honorBadge
for badgeNum in range(1, self.honorBadgeNum+1): #get Num of honorBadge
self.org_honor_badge_title[badgeNum] = self.cfg_org_rank.get('HonorBadge', str(badgeNum))
#GLOBAL RANKING
@ -51,6 +56,11 @@ class Contributor_helper:
self.rankMultiplier = cfg.getfloat('CONTRIB' ,'rankMultiplier')
self.levelMax = 16
''' HELPER '''
def getOrgLogoFromRedis(self, org):
return "{}/img/orgs/{}.png".format(self.misp_web_url, org)
def getZrange(self, keyCateg, date, topNum, endSubkey=""):
date_str = util.getDateStrFormat(date)
keyname = "{}:{}{}".format(keyCateg, date_str, endSubkey)
@ -58,6 +68,64 @@ class Contributor_helper:
data = [ [record[0].decode('utf8'), record[1]] for record in data ]
return data
''' CONTRIBUTION RANK '''
# return: [final_rank, requirement_fulfilled, requirement_not_fulfilled]
def getOrgContributionRank(self, org):
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
final_rank = 0
requirement_fulfilled = []
requirement_not_fulfilled = []
for i in range(1, self.org_rank_maxLevel+1):
key = keyname.format(org=org, orgCateg='CONTRIB_REQ_'+str(i))
if self.serv_redis_db.get(key) is None: #non existing
requirement_not_fulfilled.append(i)
else:
requirement_fulfilled.append(i)
final_rank += 1
num_of_previous_req_not_fulfilled = len([x for x in requirement_not_fulfilled if x<final_rank])
final_rank = final_rank - num_of_previous_req_not_fulfilled
return [final_rank, requirement_fulfilled, requirement_not_fulfilled]
def giveContribRankToOrg(self, org, rankNum):
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
serv_redis_db.set(keyname.format(org=orgName, orgCateg='CONTRIB_REQ_'+str(rankNum)), 1)
def removeContribRankFromOrg(self, org, rankNum):
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
serv_redis_db.delete(keyname.format(org=orgName, orgCateg='CONTRIB_REQ_'+str(rankNum)))
# 1 for fulfilled, 0 for not fulfilled, -1 for not relevant
def getCurrentContributionStatus(self, org):
final_rank, requirement_fulfilled, requirement_not_fulfilled = self.getOrgContributionRank(org)
to_ret = {}
for i in range(1, self.org_rank_maxLevel+1):
if i in requirement_fulfilled:
to_ret[i] = 1
elif i in requirement_not_fulfilled and i<=final_rank:
to_ret[i] = 0
else:
to_ret[i] = -1
return to_ret
''' HONOR BADGES '''
def getOrgHonorBadges(self, org):
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
honorBadge = []
for i in range(1, self.honorBadgeNum+1):
key = keyname.format(org=org, orgCateg='BADGE_'+str(i))
if self.serv_redis_db.get(key) is not None: #existing
honorBadge.append(i)
return honorBadge
def giveBadgeToOrg(self, org, badgeNum):
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
serv_redis_db.set(keyname.format(org=orgName, orgCateg='BADGE_'+str(badgeNum)), 1)
def removeBadgeFromOrg(self, org, badgeNum):
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
serv_redis_db.delete(keyname.format(org=orgName, orgCateg='BADGE_'+str(badgeNum)))
''' MONTHLY CONTRIBUTION '''
def getOrgPntFromRedis(self, org, date):
keyCateg = 'CONTRIB_DAY'
scoreSum = 0
@ -74,8 +142,6 @@ class Contributor_helper:
ptns = self.getOrgPntFromRedis(org, date)
return self.getTrueRank(ptns)
def getOrgLogoFromRedis(self, org):
return "{}/img/orgs/{}.png".format(self.misp_web_url, org)
def getLastContributorsFromRedis(self):
date = datetime.datetime.now()
@ -344,3 +410,50 @@ class Contributor_helper:
def TEST_getAllOrgFromRedis(self):
data2 = ['CIRCL', 'CASES', 'SMILE' ,'ORG4' ,'ORG5', 'SUPER HYPER LONG ORGINZATION NAME', 'Org3', 'MISP']
return data2
def TEST_getCurrentOrgRankFromRedis(self, org):
date = datetime.datetime.now()
points = random.randint(1,2**self.levelMax)
remainingPts = self.getRemainingPoints(points)
data = {
'org': org,
'points': points,
'rank': self.getRankLevel(points),
'remainingPts': remainingPts['remainingPts'],
'stepPts': remainingPts['stepPts'],
}
return data
def TEST_getCurrentContributionStatus(self, org):
num = random.randint(1, self.org_rank_maxLevel)
requirement_fulfilled = [x for x in range(1,num+1)]
requirement_not_fulfilled = [x for x in range(num,self.org_rank_maxLevel+1-num)]
num2 = random.randint(1, self.org_rank_maxLevel)
if num2 < num-1:
to_swap = requirement_fulfilled[num2]
del requirement_fulfilled[num2]
requirement_not_fulfilled = [to_swap] + requirement_not_fulfilled
final_rank = len(requirement_fulfilled)
to_ret = {}
for i in range(1, self.org_rank_maxLevel+1):
if i in requirement_fulfilled:
to_ret[i] = 1
elif i in requirement_not_fulfilled and i<=final_rank:
to_ret[i] = 0
else:
to_ret[i] = -1
return {'rank': final_rank, 'status': to_ret}
def TEST_getOrgHonorBadges(self, org):
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
honorBadge = []
for i in range(1, self.honorBadgeNum+1):
key = keyname.format(org=org, orgCateg='BADGE_'+str(i))
if random.randint(0,1) == 1: #existing
honorBadge.append(1)
else:
honorBadge.append(0)
print(honorBadge)
return honorBadge

View File

@ -350,7 +350,23 @@ def getOrgRank():
org = request.args.get('org')
except:
org = ''
return jsonify(contributor_helper.getCurrentOrgRankFromRedis(org))
return jsonify(contributor_helper.TEST_getCurrentOrgRankFromRedis(org))
@app.route("/_getContributionOrgStatus")
def getContributionOrgStatus():
try:
org = request.args.get('org')
except:
org = ''
return jsonify(contributor_helper.TEST_getCurrentContributionStatus(org))
@app.route("/_getHonorBadges")
def getHonorBadges():
try:
org = request.args.get('org')
except:
org = ''
return jsonify(contributor_helper.TEST_getOrgHonorBadges(org))
if __name__ == '__main__':
app.run(host='localhost', port=8001, threaded=True)

View File

@ -12,6 +12,10 @@
border: 1px solid #caccce;
}
.circlBadgeAcquired {
box-shadow: 0px 0px 15px #0000ff
}
.questionBadgeText {
left: -15%;
position: relative;

View File

@ -342,6 +342,41 @@ function updateProgressHeader(org) {
if(this.data()[5] == data.org) { row.classList.add('selectedOrgInTable'); } else { row.classList.remove('selectedOrgInTable'); }
});
});
// colorize row contribution rank help
$.getJSON( url_getContributionOrgStatus+'?org='+org, function( data ) {
var status = data['status'];
var curContributionOrgRank = data['rank'];
if (curContributionOrgRank == 0) {
$('#orgContributionRank').attr('data', '');
} else {
$('#orgContributionRank').attr('data', url_baseOrgRankLogo+curContributionOrgRank+'.svg');
}
for (var row of $('#bodyTablerankingModal')[0].children) {
row = $(row);
var rank = row.data('rank');
if(status[rank] == 0){
row.addClass("danger");
} else if(status[rank] == 1) {
row.addClass("success");
} else {
row.removeClass("success");
row.removeClass("success");
}
}
});
$.getJSON( url_getHonorBadges+'?org='+org, function( data ) {
console.log(data);
for(var i=0; i<data.length; i++) {
console.log('#divBadge_'+(i+1));
if (data[i] == 1) {
$('#divBadge_'+(i+1)).addClass('circlBadgeAcquired');
} else {
$('#divBadge_'+(i+1)).removeClass('circlBadgeAcquired');
}
}
});
}
function showOnlyOrg() {

View File

@ -96,9 +96,9 @@
<th>Contribution requirement</th>
</tr>
</thead>
<tbody>
<tbody id='bodyTablerankingModal'>
{% for item in org_rank_list %}
<tr>
<tr data-rank={{ loop.index }}>
<td style='padding: 0px; text-align: right;'><img height='35px' width='70px' style="margin-right: 20px;" src="{{ url_for('static', filename='pics/rankingMISPOrg/1.svg')[:-5]}}{{ item[0] }}.svg" type='image/svg' style="margin: auto;"</img></td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
@ -121,7 +121,7 @@
{% for item in org_honor_badge_title_list %}
<tr style="height: 85px">
<td>
<div class="circleBadge">
<div id="divBadge_{{ loop.index }}" class="circleBadge">
<img height='64px' width='64px' style="margin-top: 5px;" src="{{ url_for('static', filename='pics/MISPHonorableIcons/1.svg')[:-5]}}{{ item[0] }}.svg" type='image/svg' style="margin: auto;"</img>
</div>
</td>
@ -171,6 +171,7 @@
</div>
<button type="button" class="questionBadgeDiv" data-toggle="modal" data-target="#myModal"><i class="fa fa-question-circle questionBadgeText"></i></button>
<button id="btnCurrRank" class='btn btn-default popOverBtn' data-container='body' data-toggle='popover' style="display: none; margin-left: 20px;" onclick="showOnlyOrg()">
<object id='orgContributionRank' height=32 width=64 class="centerInBtn"></object>
<strong id="orgText" class="centerInBtn"></strong>
<div id="orgRankDiv" class='textTopHeader' style="padding-top: 0px; position: relative; width: 40px; height: 40px;"></div>
<div class='' style="float: left; padding: 10px;">
@ -351,6 +352,8 @@
var url_eventStreamLastContributor = "{{ url_for('getLastContributor') }}";
var url_getAllOrg = "{{ url_for('getAllOrg') }}";
var url_getOrgRank = "{{ url_for('getOrgRank') }}";
var url_getContributionOrgStatus = "{{ url_for('getContributionOrgStatus') }}";
var url_getHonorBadges = "{{ url_for('getHonorBadges') }}";
var url_baseRankMonthlyLogo = "{{ url_for('static', filename='pics/rankingMISPMonthly/1.svg') }}";
url_baseRankMonthlyLogo = url_baseRankMonthlyLogo.substring(0, url_baseRankMonthlyLogo.length-5);
var url_baseOrgRankLogo = "{{ url_for('static', filename='pics/rankingMISPOrg/1.svg') }}";

View File

@ -26,6 +26,7 @@ CHANNELDISP = cfg.get('RedisMap', 'channelDisp')
CHANNEL_PROC = cfg.get('RedisMap', 'channelProc')
PATH_TO_DB = cfg.get('RedisMap', 'pathMaxMindDB')
DEFAULT_PNTS_REWARD = cfg.get('CONTRIB', 'default_pnts_per_contribution')
categories_in_datatable = json.loads(cfg.get('CONTRIB', 'categories_in_datatable'))
DICO_PNTS_REWARD = {}
@ -47,6 +48,8 @@ serv_redis_db = redis.StrictRedis(
port=cfg.getint('RedisGlobal', 'port'),
db=cfg.getint('RedisDB', 'db'))
contributor_helper = contributor_helper.Contributor_helper(serv_redis_db, cfg)
reader = geoip2.database.Reader(PATH_TO_DB)
def getDateStrFormat(date):
@ -154,10 +157,11 @@ def updateOrgRank(orgName, pnts_to_add, contribType, eventTime, isClassified):
#update total points
serv_redis_db.set(keyname.format(org=orgName, orgCateg='points'), pnts_to_add)
#update contribution Requirement
heavilyCount = 10
recentDays = 31
regularlyDays = 7
heavilyCount = contributor_helper.heavilyCount
recentDays = contributor_helper.recentDays
regularlyDays = contributor_helper.regularlyDays
isRecent = True if (datetime.datetime.now() - eventTime).days > recentDays
contrib = [] #[[contrib_level, contrib_ttl], [], ...]
if contribType == 'sighting':
#[contrib_level, contrib_ttl]
@ -189,7 +193,7 @@ def updateOrgRank(orgName, pnts_to_add, contribType, eventTime, isClassified):
if contribType == 'event' and eventWeekCount>heavilyCount and isClassified:
contrib.append([14, ONE_DAY*regularlyDays])
for rankReq, ttl:
for rankReq, ttl in contrib:
serv_redis_db.set(keyname.format(org=orgName, orgCateg='CONTRIB_REQ_'+str(rankReq)), 1)
serv_redis_db.expire(keyname.format(org=orgName, orgCateg='CONTRIB_REQ_'+str(i)), ttl)