Your code worked except for a bug related to asterisk restarts that made everyone a winner. I fixed that bug and added a little to let the contest be put into a closed state by setting the winning number to 0, also fixed the bug.
Followed your instructions and it works using custom destinations.
[app-contester-reset-test1]
exten => s,1(reset),Set(GLOBAL(CONTESTER-TEST1-COUNTER)=0)
exten => s,n,Set(GLOBAL(CONTESTER-TEST1-WINNER)=0)
exten => s,n,Read(GLOBAL(CONTESTER-TEST1-WINNER),please-enter-the&count&then-press-pound,3,,,)
exten => s,n,Verbose(3,Contester: Contest counter reset to 0 winning number is set to ${CONTESTER-TEST1-WINNER})
exten => s,n,Playback(count&is-set-to)
exten => s,n,SayNumber(${CONTESTER-TEST1-WINNER},f)
exten => s,n,Playback(goodbye)
exten => s,n,Return
[app-contester-test1]
exten => s,1,GotoIf(${CONTESTER-TEST1-WINNER}?:contestover)
exten => s,n,Set(constester-call-number=${SET(GLOBAL(CONTESTER-TEST1-COUNTER)=${MATH(${CONTESTER-TEST1-COUNTER} + 1,i)})})
exten => s,n,Verbose(3,Contester: Contest caller number ${constester-call-number} of ${CONTESTER-TEST1-WINNER})
exten => s,n,Wait(1)
exten => s,n,GotoIf($["${constester-call-number}"="${CONTESTER-TEST1-WINNER}"]?winner:loser)
exten => s,n(contestover),Playback(im-sorry)
exten => s,n,Macro(hangupcall,)
exten => s,n(loser),Playback(im-sorry&you-are-caller-num)
exten => s,n,SayNumber(${constester-call-number},f)
exten => s,n,Playback(goodbye)
exten => s,n,Macro(hangupcall,)
exten => s,n(winner),Macro(user-callerid,)
exten => s,n,Verbose(3,Contester: Caller ${AMPUSER} is a winner!)
exten => s,n,Playback(you-are-caller-num)
exten => s,n,SayNumber(${constester-call-number},f)
exten => s,n,Playback(one-moment-please)
exten => s,n,Return