Messwerte auf einer Zeitleiste anzeigen

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Kiffi
Beiträge: 10725
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Messwerte auf einer Zeitleiste anzeigen

Beitrag von Kiffi »

Folgendes Szenario: Ein Tool pingt in regelmäßigen Abständen einen Server an. Das Ergebnis
wird neben zugehörigem Zeitstempel in eine Datenbank eingetragen (eine -1, wenn der Server
nicht erreichbar ist; ansonsten die Antwortzeit des Servers (aber immer > 0)).

Nun möchte ich die Messwerte grafisch anzeigen. Ich dachte da an eine ZeitLinie,
die unterschiedlich eingefärbt ist:

Bild

Grün: Server war anpingbar
Rot: Server war nicht anpingbar
Grau: Es liegen keine Messwerte vor (Tool war ausgeschaltet, o.ä.)

Ich habe aber leider keinen blassen Schimmer, wie ich sowas sinnvoll umsetzen kann.

Meine ersten Überlegungen gingen in Richtung Map (für jede Sekunde des Tages ein
Element anlegen, dann mit den Pingwerten belegen und dann wieder auf die Breite des
Bildes herunterrechnen). Aber ich denke, dass dieser Weg nicht der richtige ist.

Kann mir jemand nen Schubs geben?

Danke im voraus & Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
dige
Beiträge: 1247
Registriert: 08.09.2004 08:53

Re: Messwerte auf einer Zeitleiste anzeigen

Beitrag von dige »

Ein erster Ansatz wäre ein Count über Group By des Zeitstempels
und Umwandlung per SQL Datumfunktion auf den Tag.

Dann haste Anzahl der Messwerte pro Tag, bzw. alle Tage die
einen Messwert haben.

Oder Du gehst mit einem Startdatum Date(d, m, y...) und Iteration
+ 3600*24, tageweise durch Deinen Datenbank und selektierst
immer alle Werte pro Tag.

Dann müsstest Du noch die Werte gewichten um dich für eine
anzuzeigende Farbe zu entscheiden...
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
Kiffi
Beiträge: 10725
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Messwerte auf einer Zeitleiste anzeigen

Beitrag von Kiffi »

Hallo dige,

Danke für Deine prompte Antwort!

Das selektieren des entsprechenden Zeitraums (z.B. ein bestimmter Tag) ist kein Problem.
Dann bekomme ich aus der DB eine Anzahl von Messwerten. Im Idealfall bekomme ich dann für
24 Stunden beispielsweise alle fünf Minuten einen Wert. Wären dann 288 Werte. Die kann ich
prima in einem Image visualisieren.

Allerdings: Das Messintervall kann variieren. Ist normalerweise 240 Sekunden. Kann aber auch
drunter oder drüber sein. Im Extremfall jede Sekunde. Wären dann 86400 Werte.

Und: Wenn das Tool nicht läuft, dann habe ich zeitweise keine Messwerte = Lücken in den Intervallen.

Wenn ich von obigen Extremfall ausgehen würde, dann müsste ich eine Map (HashTable) mit
86400 Null-Elementen vorbereiten. Dann befülle ich die Map mit den Werten aus der Datenbank
(Key ist in diesem Fall der TimeStamp).

Code: Alles auswählen

NewMap HT()

StartDatum.s = "2011-10-13"
EndDatum.s   = "2011-10-14"

StartDateTime = ParseDate("%yyyy-%mm-%dd", StartDatum)
EndDateTime   = ParseDate("%yyyy-%mm-%dd", EndDatum)

For Counter = StartDateTime To EndDateTime 
  HT(Str(Counter))=0
Next

UseSQLiteDatabase()

DB = OpenDatabase(#PB_Any, MyDatabase, "", "", #PB_Database_SQLite)

Debug MapSize(HT())

Define TimeStamp.s
Define Value
Define DatabaseValues

If DatabaseQuery(DB, "Select Value, TimeStamp From Ping Where TimeStamp >= '" + StartDatum + "' And TimeStamp <= '" + EndDatum + "' And IP_Address = '192.168.1.160' Order By TimeStamp")
  
  While NextDatabaseRow(DB)
    
    Value     = GetDatabaseLong(DB, 0)
    TimeStamp = GetDatabaseString(DB, 1)
    
    HT(Str(ParseDate("%yyyy-%mm-%dd %hh.%ii.%ss", TimeStamp )))= Value
    
    DatabaseValues + 1
    
  Wend
  
  FinishDatabaseQuery(DB)
  
EndIf

Debug MapSize(HT())
Debug DatabaseValues
Jetzt habe ich ein sekundengenaues Abbild der Messwerte in der Map.
Nun müsste ich die 86400 Werte wieder auf ein darstellbares Maß reduzieren,
damit ich sie in einem Image darstellen kann.

Meines Erachtens ist obige Vorgehensweise -- wie sagt man so schön? -- 'bloated'.
Das muss doch auch eleganter gehen.

Grüße ... Kiffi
a²+b²=mc²
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: Messwerte auf einer Zeitleiste anzeigen

Beitrag von DarkDragon »

Also du musst auf jeden Fall alle Werte einmal durchgehen, es bleibt dir nichts anderes übrig. Es sei denn du speicherst von vornherein Bereiche in die Datenbank, aber da kannst du ja schlecht erkennen ob das Tool nicht gearbeitet hat.
Kiffi hat geschrieben:Meine ersten Überlegungen gingen in Richtung Map (für jede Sekunde des Tages ein
Element anlegen, dann mit den Pingwerten belegen und dann wieder auf die Breite des
Bildes herunterrechnen). Aber ich denke, dass dieser Weg nicht der richtige ist.
Guter Anfang (statt Map natürlich Array, wenn das ganze nicht zu viele Lücken hat und der Bereich nicht zu groß wird), aber wieso nicht gleich ins Bild? Also du findest den Anfangs- und Endzeitstempel heraus und rechnest den Bereich linear auf das Bild in der Breite um. Oder genauso gut umgekehrt und dann für jede X Koordinate im Bild eine Bereichsanfrage.

[EDIT]
Die Schleife also in einen StartDrawing Block und dann das hier

Code: Alles auswählen

HT(Str(ParseDate("%yyyy-%mm-%dd %hh.%ii.%ss", TimeStamp )))= Value
durch das ersetzen:

Code: Alles auswählen

    X = (ParseDate("%yyyy-%mm-%dd %hh.%ii.%ss", TimeStamp) - StartDateTime) * ImageWidth(DasBild) / (EndDateTime - StartDateTime)
    Box(X, 0, X + 1, ImageHeight(DasBild), FarbCodeVon(Value))
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
The Shark
Beiträge: 37
Registriert: 03.03.2011 00:03

Re: Messwerte auf einer Zeitleiste anzeigen

Beitrag von The Shark »

Ich würde das folgendermaßen machen:

Du liest alle Messdaten, deines Zeitraums ein und schmeisst diese in eine linked list. die Struktur der Einträge wäre folgende:

Code: Alles auswählen

Structure
  reply.i ; 1 für erreichbar, 0 für unerreichbar
  starttime.i ;Timestamp
  stoptime.i ;Timestamp
EndStructure
starttime und stoptime setzt du jeweils auf den gleichen Wert, nämlich den der Messung.
Jetzt nimmst du einfach ne Schleife und fasst aneinanderliegende Einträge zusammen, wenn stoptime(vorheriger_eintrag)-starttime(aktueller_eintrag)<zeitspanne und reply(vorheriger_wert)=reply(aktueller_wert).
Die Zeitspanne definiert dann die maximale Zeit, die die Messungen auseinander sein dürfen, um zu einem Block zu gehören. du läufst dann so oft über die Elemente, bis es nichts mehr zum Zusammenfassen gibt. Am Schluss hast du eine Liste mit Zeitbereichen, an denen der Server on- bzw offlin war. Du malst den Hindergrund grau und dann die Böcke in grün bzw. rot und fertig.

Hoffe, die Erklärung ist verstehbar, wenn nicht, kann ich noch ein kleines Pseudocodebeispiel machen. Im Erklären bin ich nämlich nicht wirklich gut ;)
Bild
Bild
Benutzeravatar
dige
Beiträge: 1247
Registriert: 08.09.2004 08:53

Re: Messwerte auf einer Zeitleiste anzeigen

Beitrag von dige »

Ich würde mir eine feste Zeitskala definieren, damit das ablesen verständlich
und nachvollziehbar bleibt. Also bspw. ein Minuten Raster. Dann alle Werte
die pro Time-Slot vorhanden sind mitteln und eintragen.

Vielleicht ist auch eine kombinierte Darstellung sinnvoll, für die Ausfallzeiten
ein extra Balken mit Grauwerten von 0...255 skaliert auf 0..100%.
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
Kiffi
Beiträge: 10725
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Messwerte auf einer Zeitleiste anzeigen

Beitrag von Kiffi »

@all: OK, Prinzip verstanden und umgesetzt. Sieht sogar ganz nett aus :-)
Muss nur noch ein paar kleine Bugs eliminieren.

Vielen Dank für Eure Hilfe :allright: & Grüße ... Kiffi
a²+b²=mc²
Antworten