optimization. I tried to improve performance, but code became ugly(