From 3377365590604b61aa2ea3172d08d830d7dbe5cc Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Sat, 6 Aug 2022 14:49:30 +1200 Subject: [PATCH] Predict next set earlier --- SetForm.tsx | 95 ++--------------------------------------------------- SetList.tsx | 93 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 87 insertions(+), 101 deletions(-) diff --git a/SetForm.tsx b/SetForm.tsx index 15e4ede..49a1e7b 100644 --- a/SetForm.tsx +++ b/SetForm.tsx @@ -1,18 +1,9 @@ -import React, { - useCallback, - useContext, - useEffect, - useRef, - useState, -} from 'react'; +import React, {useRef, useState} from 'react'; import {ScrollView, StyleSheet} from 'react-native'; -import AsyncStorage from '@react-native-async-storage/async-storage'; import DateTimePickerModal from 'react-native-modal-datetime-picker'; import {Button, TextInput} from 'react-native-paper'; -import {DatabaseContext} from './App'; -import {Plan} from './plan'; import Set from './set'; -import {DAYS, format} from './time'; +import {format} from './time'; export default function SetForm({ save, @@ -29,88 +20,6 @@ export default function SetForm({ const [showDate, setShowDate] = useState(false); const weightRef = useRef(null); const repsRef = useRef(null); - const db = useContext(DatabaseContext); - - const getTodaysPlan = useCallback(async (): Promise => { - const today = DAYS[new Date().getDay()]; - const [result] = await db.executeSql( - `SELECT * FROM plans WHERE days LIKE ? LIMIT 1`, - [`%${today}%`], - ); - return result.rows.raw(); - }, [db]); - - const getTodaysSets = useCallback(async (): Promise => { - const today = new Date().toISOString().split('T')[0]; - const [result] = await db.executeSql( - `SELECT * FROM sets WHERE created LIKE ? ORDER BY created DESC`, - [`${today}%`], - ); - return result.rows.raw(); - }, [db]); - - const getBest = useCallback( - async (query: string): Promise => { - const bestWeight = ` - SELECT name, reps, unit, MAX(weight) AS weight - FROM sets - WHERE name = ? - GROUP BY name; - `; - const bestReps = ` - SELECT name, MAX(reps) as reps, unit, weight - FROM sets - WHERE name = ? - AND weight = ? - GROUP BY name; - `; - const [weightResult] = await db.executeSql(bestWeight, [query]); - if (!weightResult.rows.length) - return { - weight: 0, - name: '', - reps: 0, - created: new Date().toISOString(), - id: 0, - }; - const [repsResult] = await db.executeSql(bestReps, [ - query, - weightResult.rows.item(0).weight, - ]); - return repsResult.rows.item(0); - }, - [db], - ); - - const predict = useCallback(async () => { - if ((await AsyncStorage.getItem('predictiveSets')) === 'false') return; - const todaysPlan = await getTodaysPlan(); - if (todaysPlan.length === 0) return; - const todaysSets = await getTodaysSets(); - const todaysWorkouts = todaysPlan[0].workouts.split(','); - let nextWorkout = todaysWorkouts[0]; - if (todaysSets.length > 0) { - const count = todaysSets.filter( - s => s.name === todaysSets[0].name, - ).length; - const maxSets = await AsyncStorage.getItem('maxSets'); - nextWorkout = todaysSets[0].name; - if (count >= Number(maxSets)) - nextWorkout = - todaysWorkouts[todaysWorkouts.indexOf(todaysSets[0].name!) + 1]; - } - const best = await getBest(nextWorkout); - setName(best.name); - setReps(best.reps.toString()); - setWeight(best.weight.toString()); - setUnit(best.unit); - repsRef.current?.focus(); - }, [getTodaysSets, getTodaysPlan, getBest]); - - useEffect(() => { - if (set.id || set.name) return; - predict(); - }, [predict, set.id, set.name]); const onConfirm = (date: Date) => { setCreated(date); diff --git a/SetList.tsx b/SetList.tsx index 48f9cf6..d33e21a 100644 --- a/SetList.tsx +++ b/SetList.tsx @@ -5,17 +5,21 @@ import { } from '@react-navigation/native'; import React, {useCallback, useContext, useEffect, useState} from 'react'; import {FlatList, StyleSheet, View} from 'react-native'; +import AsyncStorage from '@react-native-async-storage/async-storage'; import {List, Searchbar} from 'react-native-paper'; import {DatabaseContext} from './App'; import {HomePageParams} from './HomePage'; import MassiveFab from './MassiveFab'; +import {Plan} from './plan'; import Set from './set'; import SetItem from './SetItem'; +import {DAYS} from './time'; const limit = 15; export default function SetList() { const [sets, setSets] = useState(); + const [nextSet, setNextSet] = useState(); const [offset, setOffset] = useState(0); const [search, setSearch] = useState(''); const [refreshing, setRefreshing] = useState(false); @@ -39,12 +43,6 @@ export default function SetList() { setEnd(false); }, [search, db, selectSets]); - useFocusEffect( - useCallback(() => { - refresh(); - }, [refresh]), - ); - const refreshLoader = useCallback(async () => { setRefreshing(true); refresh().finally(() => setRefreshing(false)); @@ -54,6 +52,85 @@ export default function SetList() { refresh(); }, [search, refresh]); + const getTodaysPlan = useCallback(async (): Promise => { + const today = DAYS[new Date().getDay()]; + const [result] = await db.executeSql( + `SELECT * FROM plans WHERE days LIKE ? LIMIT 1`, + [`%${today}%`], + ); + return result.rows.raw(); + }, [db]); + + const getTodaysSets = useCallback(async (): Promise => { + const today = new Date().toISOString().split('T')[0]; + const [result] = await db.executeSql( + `SELECT * FROM sets WHERE created LIKE ? ORDER BY created DESC`, + [`${today}%`], + ); + return result.rows.raw(); + }, [db]); + + const getBest = useCallback( + async (query: string): Promise => { + const bestWeight = ` + SELECT name, reps, unit, MAX(weight) AS weight + FROM sets + WHERE name = ? + GROUP BY name; + `; + const bestReps = ` + SELECT name, MAX(reps) as reps, unit, weight + FROM sets + WHERE name = ? + AND weight = ? + GROUP BY name; + `; + const [weightResult] = await db.executeSql(bestWeight, [query]); + if (!weightResult.rows.length) + return { + weight: 0, + name: '', + reps: 0, + created: new Date().toISOString(), + id: 0, + }; + const [repsResult] = await db.executeSql(bestReps, [ + query, + weightResult.rows.item(0).weight, + ]); + return repsResult.rows.item(0); + }, + [db], + ); + + const predict = useCallback(async () => { + if ((await AsyncStorage.getItem('predictiveSets')) === 'false') return; + const todaysPlan = await getTodaysPlan(); + if (todaysPlan.length === 0) return; + const todaysSets = await getTodaysSets(); + const todaysWorkouts = todaysPlan[0].workouts.split(','); + let nextWorkout = todaysWorkouts[0]; + if (todaysSets.length > 0) { + const count = todaysSets.filter( + s => s.name === todaysSets[0].name, + ).length; + const maxSets = await AsyncStorage.getItem('maxSets'); + nextWorkout = todaysSets[0].name; + if (count >= Number(maxSets)) + nextWorkout = + todaysWorkouts[todaysWorkouts.indexOf(todaysSets[0].name!) + 1]; + } + const best = await getBest(nextWorkout); + setNextSet({...best, created: new Date().toISOString()}); + }, [getTodaysSets, getTodaysPlan, getBest]); + + useFocusEffect( + useCallback(() => { + refresh(); + predict(); + }, [refresh, predict]), + ); + const renderItem = useCallback( ({item}: {item: Set}) => ( @@ -90,8 +167,8 @@ export default function SetList() { weight: 0, unit: 'kg', }; - navigation.navigate('EditSet', {set}); - }, [navigation]); + navigation.navigate('EditSet', {set: nextSet || set}); + }, [navigation, nextSet]); return (