Compare commits

..
4 changed files with 31 additions and 2 deletions
@@ -248,6 +248,7 @@ class AnalysisProvider extends ChangeNotifier {
String? sessionId,
int? distance,
String? caliber,
int? expectedShots,
}) async {
if (_imagePath == null || _targetType == null) {
_errorMessage = "Impossible d'exporter : image ou type de cible manquant.";
@@ -273,6 +274,7 @@ class AnalysisProvider extends ChangeNotifier {
shots: _shots,
distanceMeters: distance ?? 25,
caliber: caliber ?? 'unknown',
expectedShots: expectedShots,
);
_state = AnalysisState.success;
+6 -1
View File
@@ -784,7 +784,7 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
// qu'elle ressorte sur le bouton.
color: Colors.white,
),
label: 'TERMINER TOUT ET EXPORTER',
label: 'TERMINER ET CONTRIBUER À L\'IA',
color: AppTheme.warningColor,
onPressed: () =>
_finishSession(context, provider, export: true),
@@ -943,6 +943,11 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
sessionId: sessionProvider.activeSessionId,
distance: sessionProvider.distance,
caliber: sessionProvider.currentWeaponCaliber,
// Hors session, shotsPerTarget vaut sa valeur par defaut : mieux
// vaut ne rien annoncer qu'annoncer un nombre faux.
expectedShots: sessionProvider.isSessionActive
? sessionProvider.shotsPerTarget
: null,
);
messenger.hideCurrentSnackBar();
}
+17 -1
View File
@@ -462,7 +462,23 @@ class _SettingsScreenState extends State<SettingsScreen> {
),
const SizedBox(height: 14),
const Text(
'🔒 Anonymat Garanti : L\'envoi est totalement anonymisé. Votre identité est remplacée par un hash cryptographique.',
'📤 Ce qui est envoyé : la photo de la cible, la position des '
'impacts que vous avez placés, la distance de tir, le calibre et '
'le nombre de coups prévus.',
style: TextStyle(fontSize: 13),
),
const SizedBox(height: 10),
const Text(
'🚫 Ce qui ne l\'est pas : la géolocalisation de la photo (retirée '
'avant l\'envoi), le nom de votre arme, et le modèle de votre appareil.',
style: TextStyle(fontSize: 13),
),
const SizedBox(height: 10),
const Text(
'🔒 Pseudonymat : votre identité est remplacée par un hash '
'cryptographique. Il reste le même d\'un envoi à l\'autre, afin de '
'rattacher vos contributions à votre compte (récompenses, '
'modération, suppression sur demande).',
style: TextStyle(fontSize: 13),
),
const SizedBox(height: 10),
+6
View File
@@ -108,6 +108,7 @@ class AiExportService {
required List<Shot> shots,
int distanceMeters = 25,
String caliber = 'unknown',
int? expectedShots,
String? apiUrl,
}) async {
try {
@@ -172,6 +173,11 @@ class AiExportService {
"type": targetType.name,
"distance_meters": distanceMeters,
"caliber": caliber,
// Nombre de coups prevus pour cette cible, null hors session.
// Un ecart avec le nombre d'impacts ne signifie pas que le
// marquage est faux (un coup peut etre parti hors papier) : c'est
// au tri du dataset d'en decider, pas au client.
"expected_shots": expectedShots,
},
"plotting": {
"target_corners": corners,