Débutant : Incompréhension de calcul avec progressbar et timer [Résolu]

jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 28 mai 2016 à 16:29 - Dernière réponse : jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention
- 3 juin 2016 à 07:41
Bonjour,

J'essaie de me faire un petit programme qui me permettrai de faire descendre une progressbar qui représente une quantité de liquide selon une heure défini par l'utilisateur.

Textbox1.text correspond à la contenance de base (exemple : 4000ml)
Textbox2.text correspond à la dose qui sera soustrait à l'heure souhaité (exemple : 200 ml)
Label99.text correspond au résultat
label78.text me permet de faire la boucle de soustraction à chaque fois que l'heure réel arrive à l'heure choisie par l'utilisateur

L'heure choisi par l'utilisateur est saisi dans le Textbox9.text pour les heures et le Textbox10.text pour les minutes

- J'active le timer pour récupéré mon heure

Private Sub RibbonForm1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Démarrage de l'heure en temps réel
Timer1.Enabled = True
End Sub


- Je récupère l'heure de l'utilisateur au bon format dans le label89.text

Private Sub TextBox10_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox10.TextChanged

'récupération de l'heure au bon format
Label89.Text = TextBox9.Text + ":" + TextBox10.Text + ":00"

End Sub


- Je récupère et compare l'heure de l'ordi par rapport à l'heure utilisateur dans le Toolstrplabel4.text

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

Timer1.Start()

'Affiche la date
ToolStripLabel2.Text = Date.Now.ToString("dd-MM-yyyy")

'Affiche l'heure
ToolStripLabel4.Text = TimeOfDay

'Résulat Pompe1
If Label89.Text = Toolstriplabel4.Text Then

Label99.Text = Label78.Text - TextBox7.Text
Label10.Text = Label99.Text + " ml"

'Calcul pourcentage
Label112.Text = (100 * Val(Label99.Text)) / Val(TextBox1.Text)
VerticalProgressBar1.Value = Label112.Text
Label117.Text = Label112.Text + " %"
Label78.Text = Label99.Text ' -> Quand j'ajoute cette ligne le calcul n'est plus cohérent

End If

End Sub




Je m'arrache les cheveux à essayer de comprendre pourquoi le calcul s’exécute mais me donne des résultats incohérent (exemple pour 4000ml de base avec 200ml de dosage, le résultat me donne 2000ml au lieu de 3800ml

Ce qui est étrange c'est que si je n'utilise pas la nation de l'heure et que je place directement les calculs dans un événement Button_Click tout fonctionne à merveille. j'ai bien 200ml en moins à chaque clique sur le bouton...

Auriez-vous une idée ou une solution à mon problème je ne sais plus quoi faire
Merci à tous ceux qui pourront m'aider
Afficher la suite 

38 réponses

Répondre au sujet
vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention - Modifié par vb95 le 28/05/2016 à 17:21
+1
Utile
3
Bonjour
J'irais même plus loin
1) Donne des noms significatifs à tes contrôles Label, TextBox . Par exemple Dosage.Text est plus parlant que Label199.Text
2) Les contrôles ne servent que pour entrer ou afficher des informations . Leurs contenus ne doivent pas servir au calcul : passe par des variables numériques intermédiaires
Un exemple simple

Nombre1.Text = "112"
Nombre2.Text = "27"
Dim Nb1 as Integer = Convert.toInt32(Nombre1.Text) ' variable numérique Nombre1
Dim Nb2 as Integer = Convert.toInt32(Nombre2.Text) ' variable numérique Nombre2
Dim Somme as Integer = Nb1 + Nb2 ' opération sur des numériques
LabelSomme.Text = Somme.Tostring ' affichage somme


Ensuite ce sera bien plus clair pour toi et pour nous aussi pour t'aider

La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. 
Cette réponse vous a-t-elle aidé ?  
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 28 mai 2016 à 17:05
Salut Vb je plussoie
vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention > Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 28 mai 2016 à 17:14
Salut Whismeril et aussi à Ucfoutu
Je te laisse ce plaisir : plussoyez mon cher
jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 28 mai 2016 à 18:53
Ok je vais essayer cela VB95
Merci je vais essayer de mettre à jours mon code celon ton exemple
Commenter la réponse de vb95
ucfoutu 18021 Messages postés lundi 7 décembre 2009Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 28 mai 2016 à 16:40
0
Utile
Bonjour,
Ton label contient du TEXTE. A convertir en numérique, si tu veux l'utiliser pour faire des opérations.
Commenter la réponse de ucfoutu
jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 28 mai 2016 à 19:32
0
Utile
7
les ligne 4 à 6 tu les places en dessous de Public Class Form1 ??
car j'ai des erreur
vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention > jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 28 mai 2016 à 23:45
Les lignes 4 à 6 dimensionnent les variables ( c'est à dire les déclarent et leur associent un type : ici Integer ( soit le type Entier signé sur 32 bits) et les initialisent à leurs valeurs selon le contenu de la TextBox .
Pour la ligne 6 je fais juste l'addition que j'affiche dans un label Labelsomme grace à la méthode .ToString
C'est le B.A.B.A e VB net
jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 1 juin 2016 à 18:36
Bonjour vb95,

J'ai réussi à avancer un peu sur ce que je souhaites faire mais il me manque juste une soustraction qui me fait foirer le calcul et je ne comprend pas pk...

Mon code actuel n'est pas très propre sur certain point mais je coince..

Pour rappel voici ce que j'aimerai faire :

Exemple :

aujourd'hui à 19:00:00
base1 = 4000ml
dose1 = 200ml
reste1 = 3800 ml
% = 95%

demain à 19:00:00
base1 = 3800ml
dose1 toujours 200ml
reste1 = 3600ml
% = 90%

Après demain à 19:00:00
base1 = 3600ml
dose1 toujours 200ml
reste1 = 3400ml
% = 85%
Ect...

Voici mon code actuel :

Public Class RibbonForm1 

Private Alarm1 As DateTime = DateTime.MaxValue ' No alarm
Private QtyBase1 As Integer = 0
Private QtyDose1 As Integer = 0
Private QtyReste1 As Integer = 0


Private Sub RibbonForm1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Timer1.Start()

VerticalProgressBar1.Maximum = 100
VerticalProgressBar1.Minimum = 0

End Sub


Private Sub SetAlarmButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SetAlarmButton1.Click


Alarm1 = Date.Now 'date du jour
Timer1.Enabled = True

End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

'Je récupère l'heure du PC
LblStatut1.Text = Date.Now.ToLongTimeString

'Je récupère l'heure au bon format de dosage souhaité via 2 txtbox
LblStatut2.Text = txtHeures1.Text + ":" + txtMinutes1.Text + ":00"

'Si l'heure du PC = heure choisi par user alors le volume de la base baisse
If LblStatut2.Text = LblStatut1.Text Then

Alarm1 = DateTime.MaxValue ' Show alarm only once
QtyBase1 = Integer.Parse(txtQtyBase1.Text)
QtyDose1 = Integer.Parse(txtQtyDose1.Text)
QtyReste1 = Integer.Parse(LBL_Reste1.Text)

'Calcul du reste de ml dans la base
Dim reste1 As Integer = CInt(QtyBase1 - QtyDose1)
LBL_Reste1.Text = reste1.ToString

'Affichage reste ml pour user
Label10.Text = reste1.ToString + " ml"

'Calcul du % restant
Dim pct1 As Integer = CInt(100 * reste1 / QtyBase1)
VerticalProgressBar1.Value = pct1
LBLresultat_prc1.Text = pct1.ToString

'Affichage % pour user
Label12.Text = pct1.ToString + "%"

' Pour la boucle du lendemain il faudrai que txtQtybase1.text = LBL_Reste1.Text
à la fin de cet événement pour que le calcul redémrarre le lendemin avec bases1 - dose1 mais je n'y arrive pas le calcul me donne un résultat incohérent

End If

End Sub



QtyBase1 est la valeur qu'il doit baisser de jours en jours pour que la logique fonctionne et que les soustractions ce déduise de jours en jours.

J'ai essayé de changer la valeur de QtyBase1 par des évenements button avec perform.click ou bien un autre timer ou bien une progressbar mais le calcul me donne toujours un résultat incohérent..

Je suis bloqué de chez bloqué car plus di'dée :(

Est-ce que vous comprenez ce que j'essai de mettre en place et comment débloqué la situation ??

Vous remerciant par avance,
Très cordialement,
vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention > jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 1 juin 2016 à 21:20
bonjour
C'est déjà beaucoup mieux !
Maintenant je suppose que le PC n'est pas allumé 24 heures sur 24 ! donc si aujourd'hui j'ai 4000 ml et que j'en enlève 200 il m'en reste 3800 !
Et j'éteins le PC
Le lendemain je le rallume ! J'ai pas sauvegardé le fait qu'il m'en reste 3800 et le logiciel ne sait pas combien il reste ! Je dois bien en enlever 200 ml mais à quelle contenance il faut les enlever ..
Est-ce cela l'origine de ton problème ?

A mon avis il faut que tu sauvegardes la quantité qui reste ( soit 3800 ml la première fois) ainsi que la quantité déduite(soit 200 ml) pour les récupérer le lendemain lorsque tu rallumes le PC

Autre chose
Dim reste1 As Integer = CInt(QtyBase1 - QtyDose1)

Inutile de mettre CInt car QtyBase1 et QtyDose1 sont déjà des Integer !
donc cela devient
Dim reste1 As Integer = QtyBase1 - QtyDose1
jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention > vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention - 1 juin 2016 à 21:51
Bonsoir vb95 et merci pour ton aide précieuse :)

le logiciel sera installé sur une tablette windows qui va tourner 24h/24.
Mais tu as raison si le user quitte le logiciel, alors toutes les valeurs des txtbox et label serton sauvegardé en "propertyBinding" donc mon probleme n'est pas là.

Mon problème c'est que je n'arrive pas à faire la boucle, c'est à dire que le lendemain le calcul redémarre avec la valeur soustraite de la veille.

Une fois le 1er calcul efféctué le 1er jours, je n'arrive pas a soustraire la QtyBase1 restante pour le lendemain...

Je ne comprend pas pourquoi quand je luis dis :
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

'Je récupère l'heure du PC
LblStatut1.Text = Date.Now.ToLongTimeString

'Je récupère l'heure au bon format de dosage souhaité via 2 txtbox
LblStatut2.Text = txtHeures1.Text + ":" + txtMinutes1.Text + ":00"

'Si l'heure du PC = heure choisi par user alors le volume de la base baisse
If LblStatut2.Text = LblStatut1.Text Then

Alarm1 = DateTime.MaxValue ' Show alarm only once
QtyBase1 = Integer.Parse(txtQtyBase1.Text)
QtyDose1 = Integer.Parse(txtQtyDose1.Text)
QtyReste1 = Integer.Parse(LBL_Reste1.Text)

'Calcul du reste de ml dans la base
Dim reste1 As Integer = CInt(QtyBase1 - QtyDose1)
LBL_Reste1.Text = reste1.ToString

'Affichage reste ml pour user
Label10.Text = reste1.ToString + " ml"

'Calcul du % restant
Dim pct1 As Integer = CInt(100 * reste1 / QtyBase1)
VerticalProgressBar1.Value = pct1
LBLresultat_prc1.Text = pct1.ToString

'Affichage % pour user
Label12.Text = pct1.ToString + "%"

'Je voudrais initialisé la quantité base1 avec la nouvelle valeur
txtBase1.text = LBL_Reste1.text

End If


Donc quand j'ajoute cette dernière ligne pour l'initialisation :
 'Je voudrais initialisé la quantité base1 avec la nouvelle valeur
txtBase1.text = LBL_Reste1.text


le calcul me donne 2200ml au lieu de 3800ml...

J'ai aucune idée de pourquoi ce résultat mais j’espère vraiment trouver LA solution pour initialiser ma base selon le dernier dosage calculé..

Aurais-tu une idée ??

Merci infiniment
vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention > jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 1 juin 2016 à 22:33
Bonjsoir
tu dis : le calcul me donne 2200ml au lieu de 3800ml...
Quel calcul exactement et où est-il dans ton code ?

Autre chose aussi des fois que :
'Je voudrais initialisé la quantité base1 avec la nouvelle valeur
txtBase1.text = LBL_Reste1.text

ce serait pas plutôt
'Je voudrais initialiser la quantité base1 avec la nouvelle valeur
txtQtyBase1.text = LBL_Reste1.text
Commenter la réponse de jerlo11
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - Modifié par Whismeril le 1/06/2016 à 22:54
0
Utile
4
Bonsoir

ça n'est pas le fond d problème, mais dans cette ligne
           Dim reste1 As Integer = CInt(QtyBase1 - QtyDose1)

les variables sont des entiers, donc le résultat aussi, il est inutile de faire une conversion.

Je rebondis sur cette phrase
Mais tu as raison si le user quitte le logiciel, alors toutes les valeurs des txtbox et label serton sauvegardé en "propertyBinding" donc mon probleme n'est pas là.


Le code que tu montres ne fais pas de binding, au contraire tout est affiché "à la main".
Si tu veux voir ce que donne le binding en .Net, j'ai écrit un petit tuto dessus pour Winform http://codes-sources.commentcamarche.net/faq/1291-utilisation-du-binding-au-travers-de-l-objet-databindingsource
C'est autrement plus puissant pour WPF.

A l'instar de VB, puisqu'il s'agit d'un calcul quotidien (si j'ai bien compris), je sauverai chaque jours tous les paramètres, dans un fichier xml, json ou même bases de données (mais 365 enregistrements / an ne le justifient peut être pas).

Toutes ces valeurs serraient stockées dans une list(of) ou autre collection (BindingList, ObservableCollection {qui a l'avantage de posséder des événements sur l'ajout ou la suppression}...).

Ainsi, tu pourrais refaire tes calculs, corriger une valeur mal saisie, ect... et en cas de démarrage de l'appli, tu recharges les données.

Quand j'étais petit, la mer Morte n'était que malade.
George Burns
vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention - 1 juin 2016 à 23:03
Salut Whis
Pour la ligne avec des entiers au début de ton message je lui ai déjà dit !
Quant à la sauvegarde des données j'attendais d'en savoir un peu plus ( pour moi un simple fichier .txt était bien suffisant pour sauvegarder et recharger les paramètres chaque jour )
Jamais essayer le binding en Net : j'en ai jamais eu besoin personnellement pour l'instant donc je ne peux pas juger
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention > vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention - 1 juin 2016 à 23:39
Oui le txt, ou le csv suffit, mais l'avantage du xml ou du json c'est que c'est lisible par un humain facilement car chaque valeur est associée à son paramètre, et donc consultable/modifiable avec un simple block note.

<Base1>4000</Base1>
<Dose1>200</Dose1>
<Reste1>3800</Reste1>
pour le xml, et un truc comme ça pour le json

base1:4000
dose1:200
reste1:3800


Quand au binding, t'en as eu besoin, chaque affichage dans un contrôle peut passer par binding, mais comme tu ne connais pas tu n'as pas essayé ou n'y a pas pensé.
Le méga gros avantage c'est que peut importe ce que tu veux afficher ou récupérer dans un textbox par exemple le binding gère la conversion en string pour l'affichage et la conversion dans l'autre sens pour la lecture.
Si tu as une collection que tu veux afficher dans une ListBox ou un Datagridview, ça te crées les colonnes, gères les formats, affiche tous les enregistrements, gères la création / modification / suppression.
Tu n'as (presque) rien à faire.
jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 2 juin 2016 à 07:53
Bonjour Whismeril,

Effectivement la sauvegarde des données n'est pas l'objet de mon pb mais vraiment le calcul en soit.

Tu pense que si j'enlève le CInt du reste1 ce calcul fonctionnerai :

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

'Je récupère l'heure du PC
LblStatut1.Text = Date.Now.ToLongTimeString

'Je récupère l'heure au bon format de dosage souhaité via 2 txtbox
LblStatut2.Text = txtHeures1.Text + ":" + txtMinutes1.Text + ":00"

'Si l'heure du PC = heure choisi par user alors le volume de la base baisse
If LblStatut2.Text = LblStatut1.Text Then

Alarm1 = DateTime.MaxValue ' Show alarm only once
QtyBase1 = Integer.Parse(txtQtyBase1.Text)
QtyDose1 = Integer.Parse(txtQtyDose1.Text)
QtyReste1 = Integer.Parse(LBL_Reste1.Text)

'Calcul du reste de ml dans la base
Dim reste1 As Integer = QtyBase1 - QtyDose1
LBL_Reste1.Text = reste1.ToString

'Affichage reste ml pour user
Label10.Text = reste1.ToString + " ml"

'Calcul du % restant
Dim pct1 As Integer = 100 * reste1 / QtyBase1
VerticalProgressBar1.Value = pct1
LBLresultat_prc1.Text = pct1.ToString

'Affichage % pour user
Label12.Text = pct1.ToString + "%"

'Je voudrais initialisé la quantité base1 avec la nouvelle valeur
txtQtyBase1.text = LBL_Reste1.text

End If



J'essayerai en rentrant ce soir ce code pour voir si cela change la donne.
Merci pour vos retours en tout cas :)
vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention > jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 2 juin 2016 à 12:49
Enlever le CInt ne change rien !
Je t'ai mis un message à la fin de ce post !
J'attends ta réponse
Commenter la réponse de Whismeril
jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 2 juin 2016 à 07:41
0
Utile
16
Bonjour,

ben le calcul executé dans le Timer1_Tick, si je traduis ce qu'il ce passe :
avec txtbase = 4000 ml
avec txtdose = 200 ml

Je compare l'heure du PC avec l'heure saisi

Si l'heure saisie = heure du PC alors
le label reste1 = QTE saisie par utilisateur soit 4000 - quantité de la dose à enlever soit 200

donc label reste1 = 3800ml

calcul du pourcentage restant = (100 * reste1 / QTE saisie par utilisateur)
= 95%

Puis il faut que je lui dise que MAINTENANT la base à baissée pour que le prochain calcul me donne :

label reste1 = 3800 - 200 = 3600ml
pourctentage = 90%

ect...

c'est cette boucle que je n'arrive pas a réaliser et qui me donne 2200ml au lieu de 3800ml
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention > jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 2 juin 2016 à 19:12
Si t'es pas à quelques secondes près tu peux même mettre 5 ou 10.

Ou tu fais comme dans mon exemple ,tu testes si l'heure est supérieure ou égale et si oui tu arrêtes le timer
ucfoutu 18021 Messages postés lundi 7 décembre 2009Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention > jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 2 juin 2016 à 19:15
Bonjour, jerlo11,
Juste pour te dire, sans sortit de St-Cyr et sans rien connaître de VB.Net ( mais quel que soit le langage), tout est dans l'art (et la logique) de déduire si l'heure est supérieure ou égale à celle prévue et de ne pas déduire à nouveau tant que la date de la dernière déduction n'est pas inférieure à celle du jour.
(mais je ne suis qu'un émotif-actif-primaire).
Après : quelel que puisse être la manière et quel que puisse être le lieu de stockage de ces informations nécessaires, ce n'est qu'un aspect très secondaire).
jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 2 juin 2016 à 20:21
vb95 tu as mis le doigt sur mon problème et tu la résolu :) Pour le moment tout s’exécute comme je le souhaite enfin !!!! sa fait 10 jours que je m'arrache les cheveux sur ce pb alors que c'était tellement basique et logique ...

Merci à tous pour vos partages de connaissance sans lesquels je n'aurai pu avancer :)
Merci a Whismeril pour ton exemple concret que je vais tester d'un autre côté :)

Un grand merci à tous ;)
vb95 1386 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 12 décembre 2017 Dernière intervention > jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 2 juin 2016 à 21:09
Bienheureux que ce soit résolu !
Et un merci à Whismeril d'avoir parlé de cycle : ça m'a mis la puce à l'oreille
jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 3 juin 2016 à 07:41
Effectivement un grand merci à vous 2 ;)
Commenter la réponse de jerlo11
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 2 juin 2016 à 14:52
0
Utile
2
Alors, un petit exemple, ou j'ai pris quelques libertés plutôt que revenir poser pleins de questions.
J'ai commenté ces "libertés" par "il me semblait logique...." au dans le style.

Tout d'abord la classe qui va contenir les paramètre, gérer les intervalles et signaler le nouveau solde, le seuil d'alerte etc...

J'ai fait en sorte que tout soit paramétrable si un jour tu veux passer de 24h à quelques secondes.
Je pense avoir suffisamment commenté, mais si t'as des questions n'hésite pas. J'ai pris quelques précautions que je ne sais pas si elles sont nécessaire en basic.
Imports System.Text
Imports System.Threading.Tasks
Imports System.Timers
Imports System.Windows.Threading


	''' <summary>
	''' Délégué décrivant la signature de l'évenement alertant le passage du seuil
	''' </summary>
	''' <param name="QuantiteRestante"></param>
	Public Delegate Sub SeuilAtteintEvent(ByVal QuantiteRestante As Integer)

	Public Delegate Sub DiversEvent()

	Public Class LeTrucAJerlo
		'Puisque ton besoin est d'une fois par jour un timer à le seconde est sur-qualitatif
		'mais pour l'exemple je vais te le faire toutes les 10s...
		Private monTimer As New Timer(1000)

		'Association d'une date à attendre et d'un débit
		Private echeance As KeyValuePair(Of Date, Integer)

		'Cet objet sert à parler en dehors du timer sans poser de problèmes inter thread
		Private dispacther As Dispatcher

		''' <summary>
		''' Construction d'un nouveau Truc avec les paramètres d'initialisation utiles
		''' </summary>
		''' <param name="QuantiteDepart"></param>
		''' <param name="DebitDefaut"></param>
		''' <param name="SeuildAlerte"></param>
		''' <param name="HeureDefaut"></param>
		Public Sub New(ByVal QuantiteDepart As Integer, ByVal DebitDefaut As Integer, ByVal SeuildAlerte As Integer, ByVal HeureDefaut As TimeSpan, Optional ByVal ProchaineEcheanceAjouteeEtAttendueAutomatiquement As Boolean = True)
			dispacther = Dispatcher.CurrentDispatcher

			QuantiteInitiale = QuantiteDepart
			DebitParDefaut = DebitDefaut
			SeuilAlerte = SeuildAlerte
			HeureParDefaut = HeureDefaut

			LesDebits = New Dictionary(Of Date, Integer)()
			AddHandler monTimer.Elapsed, AddressOf monTimer_Elapsed

			If ProchaineEcheanceAjouteeEtAttendueAutomatiquement Then
				AjouterEcheance()
			End If
		End Sub



		#Region "Propriétés"
		Public Property QuantiteInitiale() As Integer

		Public Property DebitParDefaut() As Integer

		Public Property SeuilAlerte() As Integer

		Public Property HeureParDefaut() As TimeSpan

		Private soldeActuel_Renamed As Integer
		''' <summary>
		''' Propriété donnant le solde actuel, elle comprend une variable interne pour signaler sont changement
		''' </summary>
		Public Property SoldeActuel() As Integer
			Get
				Return soldeActuel_Renamed
			End Get
			Private Set(ByVal value As Integer)
				'le set est privé car seul l'objet peut mettre à jour ce champ
				If value = soldeActuel_Renamed Then 'même valeur on s'en va
					Return
				End If
				soldeActuel_Renamed = value

					dispacther.Invoke(New Action(Sub() RaiseEvent QuantiteRestanteMiseAJour()), DispatcherPriority.Normal)

			End Set
		End Property


		''' <summary>
		''' Dictionnaire liant chaque débit à sa datation
		''' </summary>
		Public Property LesDebits() As Dictionary(Of Date, Integer)
		#End Region

		#Region "Méthodes"
		''' <summary>
		''' Retourne la quantité restante  maintenant
		''' </summary>
		''' <returns></returns>
		Public Function QuantiteRestante() As Integer
			Return QuantiteRestante(Date.Now)
		End Function

		''' <summary>
		''' Retourne la quantité restante à un instant donné
		''' </summary>
		''' <param name="Quand"></param>
		''' <returns></returns>
		Public Function QuantiteRestante(ByVal Quand As Date) As Integer
			'on additionnes tous les débits antérieurs au moment quand
			Dim totalDebit As Integer = LesDebits.Where(Function(x) x.Key <= Quand).Sum(Function(x) x.Value)

			Dim reste As Integer = QuantiteInitiale - totalDebit

            If reste <= SeuilAlerte Then
                dispacther.Invoke(New Action(Sub() RaiseEvent SeuilAtteint(reste)), DispatcherPriority.Normal)
            End If


			Return reste
		End Function

		''' <summary>
		''' Ajoute la prochaine échéance avec les paramètres par défaut
		''' </summary>
		Public Sub AjouterEcheance()
			Dim heureCalcul As Date = Date.Now.Date + HeureParDefaut

			'si l'heure est déjà passée ce sera pour le lendemain
			If heureCalcul < Date.Now.Date Then
				heureCalcul = heureCalcul.AddDays(1)
			End If

			AjouterEcheance(heureCalcul, DebitParDefaut)
		End Sub

		''' <summary>
		''' Ajoute une échéance
		''' </summary>
		Public Sub AjouterEcheance(ByVal [Date] As Date, ByVal CeDebit As Integer)
			LesDebits.Add([Date], CeDebit)

			'il me parrait logique de lancer l'attente automatiquement mais si ça te covinet pas il suffit de supprimer la ligne suivante
			AttendreLaProchaineEcheance()
		End Sub

		''' <summary>
		''' Lance la procédure pour attendre l'échéance suivante
		''' </summary>
		Public Sub AttendreLaProchaineEcheance()
			'on vérife qu'on est pas déjà en train d'attendre
			If monTimer.Enabled Then
				Return
			End If

			'on vérifie qu'il y a une échéance à attendre
			If LesDebits.Last().Key < Date.Now Then

                dispacther.Invoke(New Action(Sub() RaiseEvent PasdEcheanceAVenir()), DispatcherPriority.Normal)



                'il me parrait logique d'ajouter la prochaine échéance de suite, si ça ne te convient il faudra quitter la méthode
                AjouterEcheance()
            End If

            'on prends la première échéance à venir, imaginons que l'utilisateur en rentre plein d'avance
            echeance = LesDebits.Where(Function(x) x.Key > Date.Now).First()


            'lance l'attente
            monTimer.Start()

		End Sub


		Private Sub monTimer_Elapsed(ByVal sender As Object, ByVal e As ElapsedEventArgs)
			If Date.Now >= echeance.Key Then
				monTimer.Stop()

				'la date est atteinte ou dépassée
				SoldeActuel = QuantiteRestante()

				'il me parrait logique de relancer de suite pour la prochaine échéance, si ça ne te convient il te suffit de supprimer la ligne en dessous
				AttendreLaProchaineEcheance()
			End If
		End Sub

		#End Region


		''' <summary>
		''' Evément signalant que le seuil d'alerte est atteint ou dépassé
		''' </summary>
		Public Event SeuilAtteint As SeuilAtteintEvent

		''' <summary>
		''' Evénement signalant qu'il n'y a pas déchance dans le futur
		''' </summary>
		Public Event PasdEcheanceAVenir As DiversEvent

		''' <summary>
		''' Evénement signalant la mise à jour de la quantité restante, sans passer de paramètre
		''' </summary>
		Public Event QuantiteRestanteMiseAJour As DiversEvent

	End Class




Le formulaire de test contient deux boutons et un label
Imports System.ComponentModel
Imports System.Text
Imports System.Threading.Tasks


	Partial Public Class Form1
		Inherits Form
		Private truc As LeTrucAJerlo

		Public Sub New()
			InitializeComponent()

		End Sub

		Private Sub truc_SeuilAtteint(ByVal QuantiteRestante As Integer)
			MessageBox.Show("Quantité inférieure ou égale au seuil.")
		End Sub

		Private Sub truc_QuantiteRestanteMiseAJour()
			label1.Text = "Le solde est : " & truc.SoldeActuel
		End Sub

		Private Sub truc_PasdEcheanceAVenir()
			MessageBox.Show("Il n'y a plus d'échéances.")
		End Sub


		Private Sub butNouvelleSequence_Click(ByVal sender As Object, ByVal e As EventArgs) Handles butNouvelleSequence.Click
			'cette séquence teste va arriver un un nombre de séquence insuffisant
			Dim HeureParDefautDeTest As TimeSpan = Date.Now.TimeOfDay + TimeSpan.FromSeconds(5)

			'initialisation d'un truc
			truc = New LeTrucAJerlo(4000, 200, 400, HeureParDefautDeTest)

			'on abonne les méthodes aux événements de truc
			AddHandler truc.PasdEcheanceAVenir, AddressOf truc_PasdEcheanceAVenir
			AddHandler truc.QuantiteRestanteMiseAJour, AddressOf truc_QuantiteRestanteMiseAJour
			AddHandler truc.SeuilAtteint, AddressOf truc_SeuilAtteint

			'j'ajoute des échéances personnalisées pour que l'exemple ne dure que quelques secondes
            Dim heureSuivante As Date = Date.Now.Date + HeureParDefautDeTest + TimeSpan.FromSeconds(5)
			truc.AjouterEcheance(heureSuivante, 200)

			truc.AjouterEcheance(heureSuivante.AddSeconds(5),500)

			truc.AjouterEcheance(heureSuivante.AddSeconds(10), 200)

			truc.AjouterEcheance(heureSuivante.AddSeconds(15), 500)

			truc.AjouterEcheance(heureSuivante.AddSeconds(20), 500)

		End Sub

		Private Sub button2_Click(ByVal sender As Object, ByVal e As EventArgs) Handles button2.Click
			'cette séquence teste va passer sous le seuil
			Dim HeureParDefautDeTest As TimeSpan = Date.Now.TimeOfDay + TimeSpan.FromSeconds(5)

			'initialisation d'un truc
			truc = New LeTrucAJerlo(4000, 800, 400, HeureParDefautDeTest)

			'on abonne les méthodes aux événements de truc
			AddHandler truc.PasdEcheanceAVenir, AddressOf truc_PasdEcheanceAVenir
			AddHandler truc.QuantiteRestanteMiseAJour, AddressOf truc_QuantiteRestanteMiseAJour
			AddHandler truc.SeuilAtteint, AddressOf truc_SeuilAtteint

			'j'ajoute des échéances personnalisées pour que l'exemple ne dure que quelques secondes
            Dim heureSuivante As Date = Date.Now.Date + HeureParDefautDeTest + TimeSpan.FromSeconds(5)
			truc.AjouterEcheance(heureSuivante, 800)

			truc.AjouterEcheance(heureSuivante.AddSeconds(5), 800)

			truc.AjouterEcheance(heureSuivante.AddSeconds(10), 900)

			truc.AjouterEcheance(heureSuivante.AddSeconds(15), 500)

			truc.AjouterEcheance(heureSuivante.AddSeconds(20), 500)

		End Sub

	End Class
jerlo11 79 Messages postés mardi 19 mai 2015Date d'inscription 6 décembre 2017 Dernière intervention - 2 juin 2016 à 15:49
Merci Whismeril pour cet exemple qui m'a l'air très simple et concret pour toi mais bien trop complexe pour moi malheureusement qui suis débutant :(

sa me parait peine perdu d'avance car je ne comprend pas la logique du code, je ne pensais pas que ce soit aussi compliqué de soustraire une valeur chaque jours à une heure prévu.

A moins que tu es sauvegardé ton exemple sur visual studio et que je puisse le tester et le décortiqué pour le comprendre.

J'ai l'impression qu'il n'y a dans ton exemple que 2 entrées pour l'utilisateur ? base initiale et la dose ? je ne retrouve pas de txtbox pour la dose du seuil, les heures user pour le déclenchement ect..

Moi je n'ai qu'une form : Public Class RibbonForm1

Toi tu as Public Class Form1 et un Public Class LeTrucAJerlo

Je vais essayer de trouver une solution plus simple à ma portée car là franchement je suis pommé :(

Je vais essayer de te faire un impri ecran du programme qui pour moi ne me semblai pas si compliqué que sa.
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 2 juin 2016 à 16:43
Pour le tester, c'est très simple
Tu ouvres un nouveau projet.
Tu colles le code du formulaire dans Form1, tu y ajoute un lablel et deux boutons. Tu fais en sorte que chaque bouton appelle une séquence d'exemple.
Ensuite tu ajoutes une classe, tu remplaces code par défaut par celui que la classe LeTrucAJerlo et tu lances le tout.


La classe est prévue pour avoir un comportement par défaut, à savoir chaque jour à l'heure dite la même quantité est soustraite. Mais aussi pour mettre une date et une heure personnalisées et une quantité personnalisée.


Il y a plus simple, mais là, j'ai prévu une large evolutivité, il n'y a pas grand chose à faire pour utiliser le binding et tout sauver pour le cas d'un arrêt inopiné de l'application.
Commenter la réponse de Whismeril

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.