Débutant : Incompréhension de calcul avec progressbar et timer

Résolu
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022 - Modifié par vb95 le 28/05/2016 à 17:22
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022 - 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

6 réponses

vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
Modifié par vb95 le 28/05/2016 à 17:21
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. 
1
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
28 mai 2016 à 17:05
Salut Vb je plussoie
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169 > Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024
Modifié par vb95 le 28/05/2016 à 17:15
Salut Whismeril et aussi à Ucfoutu
Je te laisse ce plaisir : plussoyez mon cher
0
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
28 mai 2016 à 18:53
Ok je vais essayer cela VB95
Merci je vais essayer de mettre à jours mon code celon ton exemple
0
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
28 mai 2016 à 16:40
Bonjour,
Ton label contient du TEXTE. A convertir en numérique, si tu veux l'utiliser pour faire des opérations.
0
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
28 mai 2016 à 19:32
les ligne 4 à 6 tu les places en dessous de Public Class Form1 ??
car j'ai des erreur
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
28 mai 2016 à 21:58
Bonsoir
Je me pose pas mal de questions
- Sais-tu ce que sont des variables et les différents types de variables ?
- Sais-tu ce que sont des contrôles et utiliser leurs propriétés ?
- Sais-tu quelles sont les opérations ainsi que les fonctions que l'on peut faire sur les variables
Si ce n'est pas le cas dur de t'aider de façon efficace
un cours très bien fait sur VB Net : http://plasserre.developpez.com/cours/vb-net/
0
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
28 mai 2016 à 23:05
nb1 est une variable auquel tu associe nombre1.text en numerique
oui je sais utiliser des controles (button)
et non je ne connais pas toutes les fonctions possible car je debute

dans mes labels qui affiche les resultats j'ai du oublier .Tostring à certains endroit. je vous post mon code selon ses modif demain matin
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169 > jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
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
0
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
Modifié par jerlo11 le 1/06/2016 à 19:03
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,
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169 > jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
Modifié par vb95 le 1/06/2016 à 21:23
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
0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
Modifié par Whismeril le 1/06/2016 à 22:54
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
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
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
0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656 > vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024
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.
0
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
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 :)
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169 > jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
2 juin 2016 à 07:41
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
0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
Modifié par Whismeril le 2/06/2016 à 07:54
Tout d'abord je n'ai pas réagit sur ça mais sur le fait que tu mentionnes le binding et que ton code fait l'exact contraire du binding.

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

Dans l'idéal non, tu donnes à ton programme, la quantité initiale et la valeur à enlever. Et lui à chaque cycle, il fait le calcul.

Peux tu confirmer la durée d'un cycle, tu comprendras qu'entre 1000hz et 1 fois par jour, il y a des solutions différentes à mettre en place.

Édit: il faut aussi la précision attendue sur le cycle, un timer c'est pas tout à fait stable.
0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
2 juin 2016 à 08:22
Dans ce copier / coller d'Excel (je ne peux pas mettre d'images depuis le boulot)

Date Débit Quantité
Initiale 4000
Cycle 1 200 3800
Cycle 2 200 3600
Cycle 3 200 3400
Cycle 4 200 3200


Dans la cellule C3, j'ai mis =C2-B3.
Dans C4 =C3-B4, et pas 3800-B4.
Etc...
L'idée c'est d'utiliser le résultat précédent pas de changer la formule.
0
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
2 juin 2016 à 08:37
Ne connaissant pas la quantité initiale que la personne va mettre je ne peux donc pas connaitre le nombre de cycle à programmer, et j'aimerai que le calcul s’exécute selon l'heure choisi

Oui comme le dis : L'idée c'est d'utiliser le résultat précédent pas de changer la formule.

Dans mon cas je ne change pas la formule mais j'aimerai uniquement lui dire que la base initial change pour qu'a chaque tour la valeur régresse
0
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022 > Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024
2 juin 2016 à 08:42
Dans l'idéal non, tu donnes à ton programme, la quantité initiale et la valeur à enlever. Et lui à chaque cycle, il fait le calcul.

Etant débutant je ne sais pas mettre en place ce genre de cycle dans mon programme auras-tu un exemple concret ?

Merci par avance,
0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
2 juin 2016 à 08:51
Tu n'as pas besoin de savoir quelle sera la quantité initiale, ni la valeur à enlever. Il faut savoir que ça existe et que ce sera saisie.

Oui je veux bien te faire un exemple, mais il faudrait répondre à mes interrogations du message 18
0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
2 juin 2016 à 14:52
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
0
jerlo11 Messages postés 109 Date d'inscription mardi 19 mai 2015 Statut Membre Dernière intervention 17 novembre 2022
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.
0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
Modifié par Whismeril le 2/06/2016 à 16:45
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.
0
Rejoignez-nous