Finished, untested version