mannnon commited on
Commit
1bb89a4
·
verified ·
1 Parent(s): 2516982

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +184 -0
app.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import streamlit as st
3
+
4
+ st.set_page_config(page_title="Seuils individualisés - Zebris", layout="wide")
5
+
6
+ st.title("Générateur de seuils individualisés")
7
+ st.caption("Poids + volume horaire d'entraînement → seuils personnalisés de référence")
8
+
9
+ st.subheader("Entrées athlète")
10
+
11
+ c1, c2 = st.columns(2)
12
+ with c1:
13
+ nom = st.text_input("Nom de l'athlète", value="Lucas Martin")
14
+ poids_kg = st.number_input("Poids (kg)", min_value=30.0, max_value=150.0, value=72.0, step=0.1)
15
+
16
+ with c2:
17
+ sport = st.text_input("Sport", value="Course sur route")
18
+ volume_horaire = st.number_input("Volume horaire / semaine", min_value=0.5, max_value=30.0, value=5.0, step=0.5)
19
+
20
+ poids_n = poids_kg * 9.81
21
+
22
+ # Définition de la catégorie de charge
23
+ if volume_horaire <= 3:
24
+ charge = "faible"
25
+ elif volume_horaire <= 6:
26
+ charge = "modérée"
27
+ else:
28
+ charge = "élevée"
29
+
30
+ st.info(f"Catégorie de charge retenue : **{charge}**")
31
+
32
+ # Seuils selon la charge
33
+ if charge == "faible":
34
+ force_bw_low = 0.75
35
+ force_bw_high = 1.00
36
+ pression_low = 20
37
+ pression_high = 26
38
+ cadence_low = 160
39
+ cadence_high = 172
40
+ contact_low = 70
41
+ contact_high = 74
42
+ flight_low = 26
43
+ flight_high = 30
44
+ asym_low = 6
45
+ asym_high = 10
46
+ rotation_low = 6
47
+ rotation_high = 10
48
+
49
+ elif charge == "modérée":
50
+ force_bw_low = 0.70
51
+ force_bw_high = 0.95
52
+ pression_low = 20
53
+ pression_high = 25
54
+ cadence_low = 165
55
+ cadence_high = 176
56
+ contact_low = 69
57
+ contact_high = 73
58
+ flight_low = 27
59
+ flight_high = 31
60
+ asym_low = 5
61
+ asym_high = 9
62
+ rotation_low = 5
63
+ rotation_high = 9
64
+
65
+ else:
66
+ force_bw_low = 0.65
67
+ force_bw_high = 0.90
68
+ pression_low = 20
69
+ pression_high = 24
70
+ cadence_low = 168
71
+ cadence_high = 180
72
+ contact_low = 68
73
+ contact_high = 72
74
+ flight_low = 28
75
+ flight_high = 32
76
+ asym_low = 4
77
+ asym_high = 8
78
+ rotation_low = 4
79
+ rotation_high = 8
80
+
81
+ # Conversion en Newton
82
+ force_n_low = force_bw_low * poids_n
83
+ force_n_high = force_bw_high * poids_n
84
+
85
+ st.subheader("Résumé athlète")
86
+ r1, r2, r3 = st.columns(3)
87
+ with r1:
88
+ st.metric("Poids", f"{poids_kg:.1f} kg")
89
+ with r2:
90
+ st.metric("Poids en Newton", f"{poids_n:.1f} N")
91
+ with r3:
92
+ st.metric("Charge", charge)
93
+
94
+ st.subheader("Seuils individualisés")
95
+
96
+ impact_df = pd.DataFrame({
97
+ "Variable": [
98
+ "Force talon normalisée",
99
+ "Force talon convertie",
100
+ "Pression talon",
101
+ ],
102
+ "Zone basse / faible": [
103
+ f"< {force_bw_low:.2f} BW",
104
+ f"< {force_n_low:.1f} N",
105
+ f"< {pression_low} N/cm²",
106
+ ],
107
+ "Zone attendue": [
108
+ f"{force_bw_low:.2f} à {force_bw_high:.2f} BW",
109
+ f"{force_n_low:.1f} à {force_n_high:.1f} N",
110
+ f"{pression_low} à {pression_high} N/cm²",
111
+ ],
112
+ "Zone haute / élevée": [
113
+ f"> {force_bw_high:.2f} BW",
114
+ f"> {force_n_high:.1f} N",
115
+ f"> {pression_high} N/cm²",
116
+ ],
117
+ })
118
+
119
+ dynamique_df = pd.DataFrame({
120
+ "Variable": [
121
+ "Cadence",
122
+ "Temps de contact",
123
+ "Temps de vol",
124
+ ],
125
+ "Zone basse / faible": [
126
+ f"< {cadence_low} pas/min",
127
+ f"< {contact_low} %",
128
+ f"< {flight_low} %",
129
+ ],
130
+ "Zone attendue": [
131
+ f"{cadence_low} à {cadence_high} pas/min",
132
+ f"{contact_low} à {contact_high} %",
133
+ f"{flight_low} à {flight_high} %",
134
+ ],
135
+ "Zone haute / élevée": [
136
+ f"> {cadence_high} pas/min",
137
+ f"> {contact_high} %",
138
+ f"> {flight_high} %",
139
+ ],
140
+ })
141
+
142
+ symetrie_df = pd.DataFrame({
143
+ "Variable": [
144
+ "Asymétrie force talon",
145
+ "Asymétrie force avant-pied",
146
+ "Asymétrie COP",
147
+ "Différence rotation G/D",
148
+ ],
149
+ "Zone faible": [
150
+ f"< {asym_low} %",
151
+ f"< {asym_low} %",
152
+ f"< {asym_low} %",
153
+ f"< {rotation_low}°",
154
+ ],
155
+ "Zone modérée": [
156
+ f"{asym_low} à {asym_high} %",
157
+ f"{asym_low} à {asym_high} %",
158
+ f"{asym_low} à {asym_high} %",
159
+ f"{rotation_low} à {rotation_high}°",
160
+ ],
161
+ "Zone marquée": [
162
+ f"> {asym_high} %",
163
+ f"> {asym_high} %",
164
+ f"> {asym_high} %",
165
+ f"> {rotation_high}°",
166
+ ],
167
+ })
168
+
169
+ tab1, tab2, tab3 = st.tabs(["Impact", "Dynamique", "Symétrie"])
170
+
171
+ with tab1:
172
+ st.dataframe(impact_df, hide_index=True, use_container_width=True)
173
+
174
+ with tab2:
175
+ st.dataframe(dynamique_df, hide_index=True, use_container_width=True)
176
+
177
+ with tab3:
178
+ st.dataframe(symetrie_df, hide_index=True, use_container_width=True)
179
+
180
+ st.subheader("Lecture méthodologique")
181
+ st.write(
182
+ "Ces seuils sont individualisés à partir du poids et du volume horaire d’entraînement hebdomadaire. "
183
+ "Ils constituent une base de référence personnelle de l’athlète avant toute analyse ou recommandation."
184
+ )