Skip to content

Instantly share code, notes, and snippets.

@zsol
Created September 19, 2015 14:55
Show Gist options
  • Save zsol/4294fd2c80aada0ffa67 to your computer and use it in GitHub Desktop.
Save zsol/4294fd2c80aada0ffa67 to your computer and use it in GitHub Desktop.
Oncall schedule calculator
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'])]
{
"alice": ["component1", "c2", "c3"],
"bob": ["c3", "c4", "c5"],
"charlie": ["component1", "c3", "c5"],
"dave": ["component1", "c2", "c3", "c4"]
}
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