updated with shan shi's code