*** updated and rewritten