refactor, pass all tests