updated with refactoring
updated with improved testing.