originally from a tutorial, just slightly added some features