refactor final version