1+ let video , canvas , ctx ;
2+ let pushUpCount = 0 , tokenCount = 0 ;
3+ let isCountingEnabled = false ;
4+ let currentStream ;
5+ let facingMode = "user" ;
6+
7+ // New variables for push-up detection
8+ let previousBrightness = 0 ;
9+ let brightnessDiffThreshold = 10 ; // Adjust based on testing
10+ let isGoingDown = true ;
11+ let lastPushUpTime = 0 ;
12+ let pushUpCooldown = 1000 ; // 1 second cooldown between push-ups
13+
14+ async function setupCamera ( ) {
15+ console . log ( "Setting up camera..." ) ;
16+ video = document . getElementById ( 'video' ) ;
17+ const constraints = {
18+ video : { facingMode : facingMode }
19+ } ;
20+ try {
21+ currentStream = await navigator . mediaDevices . getUserMedia ( constraints ) ;
22+ video . srcObject = currentStream ;
23+ console . log ( "Camera setup successful" ) ;
24+ } catch ( error ) {
25+ console . error ( "Camera setup failed:" , error ) ;
26+ }
27+ return new Promise ( ( resolve ) => {
28+ video . onloadedmetadata = ( ) => {
29+ console . log ( "Video metadata loaded" ) ;
30+ resolve ( video ) ;
31+ } ;
32+ } ) ;
33+ }
34+
35+ function startDetection ( ) {
36+ console . log ( "Starting detection..." ) ;
37+ if ( ! video ) {
38+ console . warn ( "Video not ready. Aborting detection start." ) ;
39+ return ;
40+ }
41+ detect ( ) ;
42+ }
43+
44+ async function detect ( ) {
45+ if ( ! isCountingEnabled ) return ;
46+ try {
47+ const imageTensor = tf . browser . fromPixels ( video ) ;
48+ const resizedImage = tf . image . resizeBilinear ( imageTensor , [ 64 , 64 ] ) ; // Smaller size for faster processing
49+ const grayImage = tf . image . rgbToGrayscale ( resizedImage ) ;
50+ const brightness = tf . mean ( grayImage ) . dataSync ( ) [ 0 ] ;
51+
52+ console . log ( "Current brightness:" , brightness . toFixed ( 2 ) ) ;
53+
54+ const brightnessDiff = brightness - previousBrightness ;
55+
56+ if ( Math . abs ( brightnessDiff ) > brightnessDiffThreshold ) {
57+ let currentTime = Date . now ( ) ;
58+ if ( currentTime - lastPushUpTime > pushUpCooldown ) {
59+ if ( isGoingDown && brightnessDiff > 0 ) {
60+ console . log ( "Push-up going up" ) ;
61+ isGoingDown = false ;
62+ } else if ( ! isGoingDown && brightnessDiff < 0 ) {
63+ pushUpCount ++ ;
64+ console . log ( "Push-up completed. Count:" , pushUpCount ) ;
65+ updateStats ( ) ;
66+ isGoingDown = true ;
67+ lastPushUpTime = currentTime ;
68+ }
69+ }
70+ }
71+
72+ previousBrightness = brightness ;
73+
74+ // Clean up tensors
75+ imageTensor . dispose ( ) ;
76+ resizedImage . dispose ( ) ;
77+ grayImage . dispose ( ) ;
78+ } catch ( error ) {
79+ console . error ( "Error during motion detection:" , error ) ;
80+ }
81+ requestAnimationFrame ( detect ) ;
82+ }
83+
84+ function updateStats ( ) {
85+ document . getElementById ( 'pushUpCount' ) . textContent = pushUpCount ;
86+ const pushUpsPerToken = parseInt ( document . getElementById ( 'pushUpsPerToken' ) . value ) ;
87+ console . log ( "Updating stats. Push-ups:" , pushUpCount , "Push-ups per token:" , pushUpsPerToken ) ;
88+ if ( pushUpCount % pushUpsPerToken === 0 ) {
89+ tokenCount ++ ;
90+ console . log ( "Token earned. New token count:" , tokenCount ) ;
91+ document . getElementById ( 'tokenCount' ) . textContent = tokenCount ;
92+ }
93+ }
94+
95+ document . getElementById ( 'switchCamera' ) . addEventListener ( 'click' , async ( ) => {
96+ console . log ( "Switching camera..." ) ;
97+ facingMode = facingMode === "user" ? "environment" : "user" ;
98+ if ( currentStream ) {
99+ currentStream . getTracks ( ) . forEach ( track => track . stop ( ) ) ;
100+ }
101+ await setupCamera ( ) ;
102+ } ) ;
103+
104+ document . getElementById ( 'startStop' ) . addEventListener ( 'click' , ( ) => {
105+ isCountingEnabled = ! isCountingEnabled ;
106+ console . log ( "Counting enabled:" , isCountingEnabled ) ;
107+ document . getElementById ( 'startStop' ) . textContent = isCountingEnabled ? 'Stop' : 'Start' ;
108+ if ( isCountingEnabled ) {
109+ startDetection ( ) ;
110+ }
111+ } ) ;
112+
113+ // Reward system
114+ const rewards = [
115+ { name : 'Extra TV time' , cost : 1 } ,
116+ { name : 'Favorite snack' , cost : 2 } ,
117+ { name : 'Movie night' , cost : 3 }
118+ ] ;
119+
120+ function displayRewards ( ) {
121+ console . log ( "Displaying rewards" ) ;
122+ const rewardsContainer = document . getElementById ( 'rewards' ) ;
123+ rewardsContainer . innerHTML = '<h3>Rewards:</h3>' ;
124+ rewards . forEach ( reward => {
125+ const button = document . createElement ( 'button' ) ;
126+ button . textContent = `${ reward . name } (${ reward . cost } tokens)` ;
127+ button . addEventListener ( 'click' , ( ) => redeemReward ( reward ) ) ;
128+ rewardsContainer . appendChild ( button ) ;
129+ } ) ;
130+ }
131+
132+ function redeemReward ( reward ) {
133+ console . log ( "Attempting to redeem reward:" , reward . name ) ;
134+ if ( tokenCount >= reward . cost ) {
135+ tokenCount -= reward . cost ;
136+ document . getElementById ( 'tokenCount' ) . textContent = tokenCount ;
137+ console . log ( "Reward redeemed. New token count:" , tokenCount ) ;
138+ alert ( `You've redeemed: ${ reward . name } ` ) ;
139+ } else {
140+ console . log ( "Not enough tokens to redeem reward" ) ;
141+ alert ( 'Not enough tokens!' ) ;
142+ }
143+ }
144+
145+ async function init ( ) {
146+ console . log ( "Initializing app..." ) ;
147+ await setupCamera ( ) ;
148+ displayRewards ( ) ;
149+ console . log ( "App initialization complete" ) ;
150+ }
151+
152+ init ( ) ;
0 commit comments