diff options
author | Erich Eckner <git@eckner.net> | 2015-11-16 17:01:51 +0100 |
---|---|---|
committer | Erich Eckner <git@eckner.net> | 2015-11-17 09:08:18 +0100 |
commit | 1d920d1dcced3b59825182520878cd7ba5672914 (patch) | |
tree | 0a0fc59648e64817e72488af591b8e471e28360a /pegelunit.pas | |
parent | e99f3fec7e287b879ceeb0f0d95185cf2ab0791e (diff) | |
download | FH-Wetter-1d920d1dcced3b59825182520878cd7ba5672914.tar.xz |
Pegel funktionieren jetzt soweit
Diffstat (limited to 'pegelunit.pas')
-rw-r--r-- | pegelunit.pas | 532 |
1 files changed, 425 insertions, 107 deletions
diff --git a/pegelunit.pas b/pegelunit.pas index 7cda392..3fe1529 100644 --- a/pegelunit.pas +++ b/pegelunit.pas @@ -5,32 +5,84 @@ unit pegelunit; interface uses - Classes, SysUtils, Graphics; + cthreads, Classes, SysUtils, Graphics, ExtCtrls, lowlevelunit, Process; type + tPegelStaende = class; + tPegelZeitGroesze = (pzgJahr,pzgMonat,pzgTag,pzgStunde,pzgMin15); - tPegelZeit = array[tPegelZeitgroesze] of integer; + tPegelZeit = array[tPegelZeitgroesze] of word; tPegelStation = (psBlankenstein,psKaulsdorf,psSaalfeld,psRudolstadt, psRothenstein,psCamburg,psMoeschlitz,psProbstzella,psKaulsdorfEichicht, psKatzhuette,psSchwarzburg,psFreienorla); - tPegel = record - zeit: tPegelZeit; - hoehe: longint; + tPegelStationsSet = set of tPegelStation; + + tPegelStand = class + private + _zeit: tPegelZeit; + _uZeit: extended; + _hoehe: longint; + procedure setzeUZeit; inline; + procedure setzeZeit; inline; + public + constructor create; + destructor destroy; override; + function schreibe: string; + procedure lade(s: string); + property zeit: extended read _uzeit; + property hoehe: longint read _hoehe; end; - pTPegel = ^tPegel; - tPegelStaende = class - werte: array[tPegelStation] of tList; + tPegelListe = class + private + inhalt: tFPList; + function rItem(i: longint): tPegelStand; + function bisekt(zeit: extended): longint; + public constructor create; destructor destroy; override; -// procedure einlesen(was: string); + procedure add(s: string); + function last: tPegelStand; + function count: longint; + property items[i: longint]: tPegelStand + read rItem; default; + function minMaxY(startZeit,stopZeit: extended): tPoint; + end; + + tPegelUpdateThread = class(tThread) + private + _besitzer: tPegelStaende; + antwort: string; + ladeProzess: tProcess; + beendet: boolean; + nPegel: tPegelStation; + procedure uebernehmen; + public + beenden: boolean; + constructor create(besitzer: tPegelStaende); + destructor destroy; override; + procedure execute; override; + end; + + tPegelStaende = class + private + bild: tImage; + werte: array[tPegelStation] of tPegelListe; + put: tPegelUpdateThread; + public + constructor create(zeichenFlaeche: tImage); + destructor destroy; override; + procedure einlesen(was: string); procedure laden(von: string); procedure speichern(nach: string); + procedure achsenZeichnen(zuZeichnen: tPegelStationsSet; startZeit,stopZeit: extended); + procedure graphenZeichnen(zuZeichnen: tPegelStationsSet; startZeit,stopZeit: extended); + procedure putBeenden; end; implementation -uses systemunit; +uses systemunit, math, unit1; const pegelStationsNamen: array[tPegelstation] of array[0..1] of string = @@ -52,18 +104,252 @@ const ((210,230,270,310),(195,210,225,240),(200,230,260,290),(150,180,210,240), (250,290,330,370),(280,330,380,430),(180,200,220,240),(0,0,0,0), (130,170,210,230),(200,230,260,290),(130,150,170,190),(0,0,0,0)); - pFarben: array[tPegelstation] of tColor = + pegelFarben: array[tPegelstation] of tColor = ($000000,$000000,$000000,$FF0000,$7F0000,$000000,$000000,$000000,$000000,$000000,$000000,$000000); + bufLengMin = 1024*1024; + +// tPegelStand ***************************************************************** + +constructor tPegelStand.create; +var + pzg: tPegelZeitGroesze; +begin + inherited create; + for pzg:=low(tPegelZeitGroesze) to high(tPegelZeitGroesze) do + _zeit[pzg]:=0; + _hoehe:=-1; +end; + +destructor tPegelStand.destroy; +begin + inherited destroy; +end; + +procedure tPegelStand.setzeUZeit; +begin + _uZeit:= + encodeDate(_zeit[pzgJahr],_zeit[pzgMonat],_zeit[pzgTag])+ + encodeTime(_zeit[pzgStunde],_zeit[pzgMin15]*15,0,0) +end; + +procedure tPegelStand.setzeZeit; +var + mi,se,hu: word; +begin + decodeDate(_uZeit,_zeit[pzgJahr],_zeit[pzgMonat],_zeit[pzgTag]); + decodeTime(_uZeit,_zeit[pzgStunde],mi,se,hu); + _zeit[pzgMin15]:=round(mi/15); +end; + +function tPegelStand.schreibe: string; +var + pzg: tPegelZeitGroesze; +begin + result:=''; + for pzg:=low(tPegelZeitGroesze) to high(tPegelZeitGroesze) do + result:=result+inttostr(_zeit[pzg])+' '; + result:=result+inttostr(_hoehe); +end; + +procedure tPegelStand.lade(s: string); +var + pzg: tPegelZeitGroesze; +begin + if pos(',',s)=0 then begin // Syntax wie in letzte_Pegel + for pzg:=low(tPegelZeitGroesze) to high(tPegelZeitGroesze) do + _zeit[pzg]:=strtoint(erstesArgument(s)); + _hoehe:=strtoint(s); + setzeUZeit; + end + else begin + {$WARNINGS-} + dateSeparator:='.'; + shortDateFormat:='d.m.y'; + {$WARNINGS+} + _uZeit:=strToDateTime(erstesArgument(s,',')); + _hoehe:=strtoint(s); + setzeZeit; + end; +end; + +// tPegelListe ***************************************************************** + +constructor tPegelListe.create; +begin + inherited create; + inhalt:=tFPList.create; +end; + +destructor tPegelListe.destroy; +begin + inhalt.free; + inherited destroy; +end; + +function tPegelListe.rItem(i: longint): tPegelStand; +begin + result:=tPegelStand(inhalt[i]); +end; + +function tPegelListe.bisekt(zeit: extended): longint; +var + mi,ma,neu: longint; +begin + mi:=0; + neu:=mi; + ma:=count; + while mi<ma do begin + neu:=(mi+ma) div 2; + if (neu>=count) or (items[neu].zeit<zeit) then begin + inc(neu); + mi:=neu; + continue; + end; + if items[neu].zeit>zeit then begin + ma:=neu; + continue; + end; + result:=neu; + exit; + end; + result:=neu; +end; + +procedure tPegelListe.add(s: string); +var + np: tPegelStand; + i: longint; +begin + np:=tPegelStand.create; + np.lade(s); + i:=bisekt(np.zeit); + if (i>=count) or (items[i].zeit<>np.zeit) then + inhalt.Insert(i,np) + else + np.free; +end; + +function tPegelListe.last: tPegelStand; +begin + result:=items[count-1]; +end; + +function tPegelListe.count: longint; +begin + result:=inhalt.count; +end; + +function tPegelListe.minMaxY(startZeit,stopZeit: extended): tPoint; +var + i: longint; +begin + result.x:=last.hoehe; + result.y:=result.x; + for i:=max(0,bisekt(startZeit)-1) to count-2 do begin + if items[i].zeit>stopZeit then break; + result.x:=min(result.x,items[i].hoehe); + result.y:=max(result.y,items[i].hoehe); + end; +end; + +// tPegelUpdateThread ********************************************************** + +constructor tPegelUpdateThread.create(besitzer: tPegelStaende); +begin + inherited create(true); + _besitzer:=besitzer; + beenden:=false; + fillchar(antwort,sizeof(antwort),#0); + setlength(antwort,0); + ladeProzess:=nil; + beendet:=false; + nPegel:=low(tPegelStation); + suspended:=false; +end; + +destructor tPegelUpdateThread.destroy; +begin + while not beendet do + sleep(100); + setlength(antwort,0); + inherited destroy; +end; + +procedure tPegelUpdateThread.uebernehmen; +begin + if beenden then exit; + _besitzer.einlesen(antwort); + setlength(antwort,0); + form1.zeichnen; +end; + +procedure tPegelUpdateThread.execute; +var + bytesToRead,bytesRead,cnt: longint; +begin + while not beenden do begin + ladeProzess:=tProcess.create(nil); + ladeProzess.options:=[poUsePipes]; + ladeProzess.executable:='/usr/bin/curl'; + ladeProzess.parameters.add('-o'); + ladeProzess.parameters.add('-'); + ladeProzess.parameters.add('http://www.tlug-jena.de/hw.inc/txt/' + // 57028.0_w_28.txt + inttostr(floor(pegelStationsNummern[nPegel]))+'.'+ + inttostr(round(10*(pegelStationsNummern[nPegel]-floor(pegelStationsNummern[nPegel]))))+ + '_w_28.txt'); + bytesRead:=0; + ladeProzess.execute; + ladeProzess.closeInput; + ladeProzess.closeStderr; + while (ladeProzess.running) or (ladeProzess.output.numBytesAvailable>0) do begin + if beenden then + ladeProzess.terminate(0); + bytesToRead:=ladeProzess.output.numBytesAvailable; + if bytesToRead>0 then begin + setlength(antwort,bytesRead + bufLengMin); + bytesRead:=bytesRead+ladeProzess.output.read(antwort[bytesRead+1],min(bytesToRead,length(antwort)-bytesRead)); + end + else + sleep(100); + end; + ladeProzess.closeOutput; + ladeProzess.free; + + if not beenden then begin + setlength(antwort,bytesRead); + + synchronize(@uebernehmen); + + if nPegel<high(tPegelStation) then + inc(nPegel) + else begin + nPegel:=low(tPegelStation); + for cnt:=0 to 599 do begin + if beenden then + break; + sleep(100); + end; + end; + + if not beenden then + sleep(100); + end; + end; + ladeProzess:=nil; + beendet:=true; +end; // tPegelStaende *************************************************************** -constructor tPegelStaende.create; +constructor tPegelStaende.create(zeichenFlaeche: tImage); var ps: tPegelStation; begin inherited create; + bild:=zeichenFlaeche; for ps:=low(tPegelStation) to high(tPegelStation) do - werte[ps]:=tList.create; + werte[ps]:=tPegelListe.create; + put:=nil; end; destructor tPegelStaende.destroy; @@ -72,6 +358,7 @@ var begin for ps:=low(tPegelStation) to high(tPegelStation) do werte[ps].free; + put.free; inherited destroy; end; @@ -80,12 +367,14 @@ var f: textfile; s: string; ps: tPegelstation; - pzg: tPegelzeitgroesze; psda,gefunden: boolean; - np: pTPegel; i: longint; begin - if not fileexists(von) then exit; + if not fileexists(von) then begin + writeln('Pegeldatei '''+von+''' existiert nicht!'); + raise exception.create('Pegeldatei '''+von+''' existiert nicht!'); + exit; + end; assignfile(f,von); reset(f); psda:=false; @@ -104,22 +393,21 @@ begin end; if not gefunden then begin closefile(f); - raise exception.create('Pegelstation '''+s+''' nicht gefunden!'); + writeln('Pegelstation '''+s+''' nicht gefunden '''+Pegelstationsnamen[psSaalfeld,0]+'''!'); + raise exception.create('Pegelstation '''+s+''' nicht gefunden '''+Pegelstationsnamen[psSaalfeld,0]+'''!'); end; psda:=true; continue; end; - if not psda then + if not psda then begin + writeln('Es wurde noch keine Pegelstation erwähnt!'); raise exception.create('Es wurde noch keine Pegelstation erwähnt!'); - getmem(np,sizeof(TPegel)); - werte[ps].Add(np); - for pzg:=low(tPegelZeitGroesze) to high(tPegelZeitGroesze) do begin - np^.Zeit[pzg]:=strtoint(copy(s,1,pos(' ',s)-1)); - delete(s,1,pos(' ',s)); end; - np^.Hoehe:=strtoint(s); + werte[ps].add(s); end; closefile(f); + if not assigned(put) then + put:=tPegelUpdateThread.create(self); end; procedure tPegelStaende.speichern(nach: string); @@ -127,9 +415,7 @@ var dateischonda: boolean; f: textfile; ps: tPegelStation; - pzg: tPegelZeitGroesze; i: longint; - s: string; begin dateischonda:=fileexists(nach); if dateischonda then @@ -139,12 +425,8 @@ begin rewrite(f); for ps:=low(tPegelStation) to high(tPegelStation) do begin writeln(f,'Station: '+Pegelstationsnamen[ps,0]); - for i:=0 to werte[ps].Count-1 do begin - s:=''; - for pzg:=low(tPegelZeitGroesze) to high(tPegelZeitGroesze) do - s:=s+inttostr(pTPegel(werte[ps][i])^.zeit[pzg])+' '; - writeln(f,s+inttostr(pTPegel(werte[ps][i])^.hoehe)); - end; + for i:=0 to werte[ps].Count-1 do + writeln(f,tPegelStand(werte[ps][i]).schreibe); end; closefile(f); if dateischonda then begin @@ -153,83 +435,119 @@ begin end; end; -(* -procedure tPegelStaende.einlesen(von: string); -var t: string; - PS: TPegelstation; - psda,wsda,gefunden: boolean; - PZ: TPegelZeit; - posi: extended; - nps: PTPegel; - PZG: TPegelZeitGroesze; - i: longint; -begin - s:=s+#10; - result:=false; - psda:=false; - wsda:=false; - PS:=low(TPegelstation); - while pos(#13,s)>0 do begin - t:=copy(s,1,pos(#10,s)-1); - delete(s,1,pos(#10,s)); - while pos(#13,t)>0 do - delete(t,pos(#13,t),1); - if length(t)=0 then continue; - if pos('Pegelname: ',t)=1 then begin - delete(t,1,pos(' ',t)); - PS:=low(TPegelstation); - gefunden:=false; - while PS<=high(TPegelstation) do begin - for i:=0 to length(Pegelstationsnamen[psBlankenstein])-1 do - gefunden:=gefunden or ((Pegelstationsnamen[PS,i]<>'') and (Pegelstationsnamen[PS,i]=t)); - if gefunden then break; - inc(PS); - end; - if not gefunden then begin - Messagedlg('Unbekannter Pegelname: '''+t+'''!',mterror,[mbOk],0); - exit; - end; - psda:=true; - continue; - end; - if t='Durchfluss [m3/s]' then begin - wsda:=false; - continue; - end; - if t='Wasserstand [cm]' then begin - wsda:=true; - continue; - end; - if not (wsda and psda) then continue; - if pos('Fluss: ',t)=1 then continue; - if pos('Flusseinzugsgebiet: ',t)=1 then continue; - if pos('Stationsnummer: ',t)=1 then begin - delete(t,1,pos(' ',t)); - while pos(' ',t)=1 do delete(t,1,1); - while pos('.',t)>0 do t[pos('.',t)]:=','; - if round(10*strtofloat(t))<>round(10*Pegelstationsnummern[PS]) then begin - Messagedlg('erwartete Pegelstationsnummer ('+floattostr(Pegelstationsnummern[PS])+ - ') für '+Pegelstationsnamen[PS,0]+' ist verschieden von der angegebenen Nummer ('+t+')!',mtError,[mbOk],0); - exit; +procedure tPegelStaende.achsenZeichnen(zuZeichnen: tPegelStationsSet; startZeit,stopZeit: extended); +var + pS: tPegelStation; + i: longint; + miMa: tPoint; +begin + for pS:=low(pS) to high(pS) do + if pS in zuZeichnen then begin + miMa:=werte[pS].minMaxY(startZeit,stopZeit); + for i:=0 to 3 do + if (pegelGrenzen[pS,i]>=miMa.x) and (pegelGrenzen[pS,i]<=miMa.y) then begin + bild.canvas.pen.color:=pegelFarben[pS]; + bild.canvas.moveTo(-10,wertZuY(pegelGrenzen[pS,i],miMa,bild.height)); + bild.canvas.lineTo(bild.width+10,wertZuY(pegelGrenzen[pS,i],miMa,bild.height)); + end; end; - continue; - end; - if pos('Hinweise: ',t)=1 then continue; - if pos('keine Werte',t)>0 then continue; - PZ:=strToPegelZeit(t); - posi:=findePegelZeit(Pegelstaende[PS],PZ); - if odd(round(2*posi)) then begin - result:=true; - getmem(nps,sizeof(TPegel)); - for PZG:=low(TPegelZeitGroesse) to high(TPegelZeitGroesse) do - nps^.Zeit[PZG]:=PZ[PZG]; - delete(t,1,pos(',',t)+1); - nps^.Hoehe:=strtoint(t); - Pegelstaende[PS].Insert(round(posi+0.5),nps); +end; + +procedure tPegelStaende.graphenZeichnen(zuZeichnen: tPegelStationsSet; startZeit,stopZeit: extended); +var + pS: tPegelStation; + miMa: tPoint; + i: longint; +begin + for pS:=low(pS) to high(pS) do + if pS in zuZeichnen then begin + miMa:=werte[pS].minMaxY(startZeit,stopZeit); + bild.canvas.pen.color:=pegelFarben[pS]; + i:=max(0,werte[pS].bisekt(startZeit)-1); + bild.canvas.moveTo(-10,wertZuY(werte[pS][i].hoehe,miMa,bild.height)); + while (i<werte[pS].count) and (werte[pS][i].zeit<=stopZeit) do begin + bild.canvas.lineTo( + wertZuX(werte[pS][i].zeit,startZeit,stopZeit,bild.width), + wertZuY(werte[pS][i].hoehe,miMa,bild.height)); + inc(i); + end; + end; +end; + +procedure tPegelStaende.einlesen(was: string); +var + t: string; + PS: TPegelstation; + psda,wsda,gefunden: boolean; + i: longint; +begin + while pos(#13,was)>0 do + delete(was,pos(#13,was),1); + psda:=false; + wsda:=false; + pS:=low(tPegelStation); + while was<>'' do begin + t:=myUtf8Encode(erstesArgument(was,#10)); + if length(t)=0 then continue; + if startetMit('Pegelname:',t) then begin + pS:=low(tPegelStation); + gefunden:=false; + while pS<=high(tPegelStation) do begin + for i:=0 to length(pegelStationsNamen[psBlankenstein])-1 do + gefunden:=gefunden or ((pegelStationsNamen[pS,i]<>'') and (pegelStationsNamen[pS,i]=t)); + if gefunden then break; + inc(pS); + end; + if not gefunden then begin + writeln('Unbekannter Pegelname: '''+t+'''!'); + for i:=1 to length(t) do + write(ord(t[i]),' '); + writeln; + for i:=1 to length(pegelStationsNamen[psSaalfeld,0]) do + write(ord(pegelStationsNamen[psSaalfeld,0][i]),' '); + writeln; + raise exception.create('Unbekannter Pegelname: '''+t+'''!'); + end; + psda:=true; + continue; + end; + if t='Durchfluss [m3/s]' then begin + wsda:=false; + continue; + end; + if t='Wasserstand [cm]' then begin + wsda:=true; + continue; + end; + if not (wsda and psda) then continue; + if pos('Fluss: ',t)=1 then continue; + if pos('Flusseinzugsgebiet: ',t)=1 then continue; + if startetMit('Stationsnummer: ',t) then begin + {$WARNINGS-} + if decimalSeparator<>'.' then + while pos('.',t)>0 do + t[pos('.',t)]:=decimalSeparator; + {$WARNINGS+} + if round(10*strtofloat(t))<>round(10*pegelStationsNummern[pS]) then begin + writeln( + 'erwartete Pegelstationsnummer ('+floattostr(pegelStationsNummern[pS])+ + ') für '+pegelStationsNamen[pS,0]+' ist verschieden von der angegebenen Nummer ('+t+')!'); + raise exception.create( + 'erwartete Pegelstationsnummer ('+floattostr(pegelStationsNummern[pS])+ + ') für '+pegelStationsNamen[pS,0]+' ist verschieden von der angegebenen Nummer ('+t+')!'); + end; + continue; + end; + if pos('Hinweise: ',t)=1 then continue; + if pos('keine Werte',t)>0 then continue; + werte[pS].add(t); end; - end; - Zeichnen; end; -*) + +procedure tPegelStaende.putBeenden; +begin + put.beenden:=true; +end; + end. |