-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmodels.py
138 lines (108 loc) · 4.44 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""Base models.
Base models shall not be modified. If they are being modified or inherited,
please move them to their own module, similar to teams or povs.
"""
import logging
from collections import defaultdict, namedtuple
from helpers import atmost_80pct, no_overhead, perfect
__author__ = "Kevin Borgolte <[email protected]>, Giovanni Vigna <[email protected]>"
class Binary(object):
"""Binary model.
A binary models the overhead and functionality of a replacement
challenge set. It expects functions that return 0..inf for overhead
and 0..1 for the functionality factor.
"""
def __init__(self, name,
overhead_time=0.0,
overhead_size=0.0,
overhead_memory=0.0,
functionality=1.0,
protection=1.0):
self.name = name
self.overhead_time = overhead_time
self.overhead_memory = overhead_memory
self.overhead_size = overhead_size
self.functionality = functionality
self.protection = protection
self.logger = logging.getLogger("binary")
def __str__(self):
s = "Binary Name: %s ot: %f om: %f os: %f f: %f" % \
(self.name,
self.overhead_time,
self.overhead_memory,
self.overhead_size,
self.functionality)
return s
#Overhead = namedtuple('Overhead', ['execution_time', 'file_size',
# 'memory_usage'])
class Service(object):
"""Service model.
A service models whether a service is active, which binary a team has
deployed, when it was last deployed, how many reference PoVs for the
service exist, and whether they were successful.
"""
def __init__(self, name, binary,
f_reference_povs_successful=atmost_80pct,
reference_povs_total=4):
self.name = name
self.binary = binary
self.round_introduced = None
self.round_last_submit = None
self.logger = logging.getLogger("service")
def activate(self, round_):
self.logger.debug("Activating service %s at round %d" % (self.name, round_))
self.round_introduced = round_
def is_active(self, round_):
if not self.round_introduced:
return False
if round_ < self.round_introduced:
return False
return True
def field(self, binary, round_):
self.logger.debug("Fielding binary %s for service %s" % (binary.name, self.name))
self.round_last_submit = round_
self.binary = binary
def is_fielded(self, round_):
"""Check if the service is fielded yet.
Per A157: A service is fielded at n+2 if the RCB was submitted in n.
Per A163: A RCB for newly introduced challenge set is fielded at n+3.
"""
if self.round_last_submit is None:
# Per A163, the binary is a newly introduced RCB
return round_ >= (self.round_introduced)
else:
return round_ > (1 + max(self.round_last_submit, # A157
self.round_introduced + 1)) # A163
def __str__(self):
s = "Service Name: %s Binary: %s Introduced: %s Last submit: %s" % \
(self.name,
self.binary.name,
self.round_introduced,
self.round_last_submit)
return s
class Round(object):
"""Round model.
A round models the successful PoVs per service per team and the scores that
were assigned to each team in this specific round.
Note that pov_successful stores the name of the target team
"""
def __init__(self, round_):
round_ = round_
self.successful = defaultdict(list)
self.scores = defaultdict(list)
def pov_successful(self, attacker, pov, target):
self.successful[pov.service.name].append((attacker.name, target.name))
def successful_attacks_performed(self, service_name, team_name):
count = 0
for attack in self.successful[service_name]:
if attack[0] == team_name:
count += 1
return count
def successful_attacks_received(self, service_name, team_name):
count = 0
for attack in self.successful[service_name]:
if attack[1] == team_name:
count += 1
return count