Created
September 19, 2015 14:55
-
-
Save zsol/4294fd2c80aada0ffa67 to your computer and use it in GitHub Desktop.
Oncall schedule calculator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Components and number of owners: | |
{u'c2': 2, | |
u'c3': 4, | |
u'c4': 2, | |
u'c5': 2, | |
u'component1': 3} | |
-------------------------------- | |
Possible minimal oncall rotations: | |
[set([u'charlie', | |
u'dave']), | |
set([u'bob', | |
u'dave']), | |
set([u'alice', | |
u'bob'])] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"alice": ["component1", "c2", "c3"], | |
"bob": ["c3", "c4", "c5"], | |
"charlie": ["component1", "c3", "c5"], | |
"dave": ["component1", "c2", "c3", "c4"] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
from pprint import pprint | |
def is_covering(subsets, all_components): | |
return all_components.issubset(set().union(flatten([components for ( | |
_, components) in subsets]))) | |
def generate_covering_set(covering_sets, remaining_sets, all_components): | |
if is_covering(covering_sets, all_components): | |
yield covering_sets | |
else: | |
for candidate in remaining_sets: | |
for nested_result in generate_covering_set( | |
covering_sets + [candidate], filter( | |
lambda x: x != candidate, remaining_sets), all_components): | |
yield nested_result | |
def flatten(l): | |
return [item for sublist in l for item in sublist] | |
def main(): | |
ownership = { | |
'alice': ['c1', 'c2', 'c3'], | |
'bob': ['c3', 'c4', 'c5'], | |
'charlie': ['c1', 'c3', 'c5'], | |
'dave': ['c1', 'c2', 'c3', 'c4'], | |
} | |
with open('ownership.json') as f: | |
ownership = json.load(f) | |
components = { | |
component: components.count(component) | |
for components in [flatten(ownership.values( | |
))] for component in components | |
} | |
print("Components and number of owners:") | |
pprint(components, width=1) | |
print("--------------------------------") | |
results = [] | |
for solutions in generate_covering_set( | |
[], list(ownership.iteritems()), set(flatten([components for ( | |
_, components) in ownership.iteritems()]))): | |
# remove uniques | |
if solutions not in results: | |
results.append(solutions) | |
minimal_results = [] | |
for solution in sorted(results, key=lambda x: len(x)): | |
names = set([name for (name, _) in solution]) | |
if all([not j.issubset(names) for j in minimal_results]): | |
minimal_results.append(names) | |
print("Possible minimal oncall rotations:") | |
pprint(minimal_results, width=1) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment