diff options
-rw-r--r-- | fhunit.pas | 583 | ||||
-rw-r--r-- | pegelunit.pas | 143 | ||||
-rw-r--r-- | unit1.lfm | 1 | ||||
-rw-r--r-- | unit1.pas | 53 | ||||
-rw-r--r-- | wetter.konf | 2 | ||||
-rw-r--r-- | wetter.lps | 164 |
6 files changed, 766 insertions, 180 deletions
@@ -5,19 +5,91 @@ unit fhunit; interface uses - Classes, SysUtils, Graphics; + CThreads, Classes, SysUtils, Graphics, ExtCtrls, Process, lowLevelUnit; type - tMessgroesze = (mgTemperatur,mgLuftfeuchte,mgWindgeschwindigkeit,mgWindrichtung, + tMessGroesze = (mgTemperatur,mgLuftfeuchte,mgWindgeschwindigkeit,mgWindrichtung, mgNiederschlag,mgGlobalstrahlung,mgLuftdruck); - tZeitgroesze = (zgJahr,zgMonat,zgTag,zgStunde,zgMin10); - tMesswerte = array[tMessgroesze] of extended; - tZeit = array[tZeitgroesze] of integer; - tMesspunkt = record - zeit: tZeit; - mW: tMesswerte; + tMessGroeszenSet = set of tMessGroesze; + tZeitGroesze = (zgJahr,zgMonat,zgTag,zgStunde,zgMin10); + tMessWerte = array[tMessGroesze] of extended; + tMessWerteExtPoints = array[tMessGroesze] of tExtPoint; + tZeit = array[tZeitGroesze] of word; + + tMessPunkte = class; + + tMessPunkt = class + private + _mZeit: tZeit; + _uZeit: extended; + _mW: tMessWerte; + procedure setzeUZeit; inline; + procedure setzeZeit; inline; + function rMW(mG: tMessGroesze): extended; inline; + public + constructor create; + destructor destroy; override; + function lade(s: string): boolean; + function schreibe: string; + property zeit: extended + read _uZeit; + property mW[mG: tMessGroesze]: extended + read rMW; + end; + + tMessPunkteListe = class + private + inhalt: tFPList; + function rItem(i: longint): tMessPunkt; + function bisekt(zeit: extended): longint; + public + constructor create; + destructor destroy; override; + function add(s: string): boolean; + function last: tMessPunkt; + function count: longint; + property items[i: longint]: tMessPunkt + read rItem; default; + function minMaxY(startZeit,stopZeit: extended): tMessWerteExtPoints; + end; + + tMessPunkteUpdateThread = class(tThread) + private + _besitzer: tMessPunkte; + antwort: string; + ladeProzess: tProcess; + beendet, + warGueltig: boolean; + nZeit: extended; + _tNum,_tAnz: longint; + procedure uebernehmen; + procedure nZeitNullen; inline; + public + beenden: boolean; + constructor create(besitzer: tMessPunkte; tNum,tAnz: longint); + destructor destroy; override; + procedure execute; override; + end; + + tMessPunkte = class + private + bild: tImage; + werte: tMessPunkteListe; + muts: array of tMessPunkteUpdateThread; + public + constructor create(zeichenFlaeche: tImage); + destructor destroy; override; + function einlesen(was: string): boolean; + procedure laden(von: string); + procedure speichern(nach: string); + procedure achsenZeichnen(zuZeichnen: tMessGroeszenSet; startZeit,stopZeit: extended); + procedure graphenZeichnen(zuZeichnen: tMessGroeszenSet; startZeit,stopZeit: extended); + procedure mutBeenden; end; +procedure uZeit2mZeit(uZ: extended; out mZ: tZeit); inline; +function strZuMZeit(s: string; out mZ: tZeit): boolean; + const messNamen: array[tMessgroesze] of string = ('Temperatur','Luftfeuchte','Windgeschwindigkeit','Windrichtung', @@ -25,12 +97,505 @@ const maszEinheit: array[tMessgroesze] of string = ('°C','%','m/s','°','mm','W/m²','mbar'); monatsNamen: array[1..12] of string = - ('Januar','Februar','März','April','Mai','Juni','Juli', + ('Januar','Februar','M'#$e4'rz','April','Mai','Juni','Juli', 'August','September','Oktober','November','Dezember'); farben: array[tMessgroesze] of tColor = ($0000DF,$CFAF7F,$007FFF,$FF00FF,$FFAF3F,$3FAFAF,$AFAFAF); implementation +uses unit1, math, systemUnit; + +// tMessPunkt ****************************************************************** + +constructor tMessPunkt.create; +var + zg: tZeitGroesze; + mg: tMessGroesze; +begin + inherited create; + for zg:=low(zg) to high(zg) do + _mZeit[zg]:=0; + _uZeit:=0; + for mg:=low(mg) to high(mg) do + _mW[mg]:=0; +end; + +destructor tMessPunkt.destroy; +begin + inherited destroy; +end; + +procedure tMessPunkt.setzeUZeit; +begin + _uZeit:= + encodeDate(_mZeit[zgJahr],_mZeit[zgMonat],_mZeit[zgTag])+ + encodeTime(_mZeit[zgStunde],_mZeit[zgMin10]*10,0,0) +end; + +procedure tMessPunkt.setzeZeit; +begin + uZeit2mZeit(_uZeit,_mZeit); +end; + +function tMessPunkt.rMW(mG: tMessGroesze): extended; +begin + result:=_mW[mG]; +end; + +function tMessPunkt.lade(s: string): boolean; +var + zG: tZeitGroesze; + mG: tMessGroesze; + t: string; + istZahl: boolean; + i: longint; +begin + result:=false; + if pos('<html>',s)=0 then begin // Format wie in letztes_Wetter.txt + {$WARNINGS-} + if decimalSeparator<>',' then + while pos(',',s)>0 do + s[pos(',',s)]:=decimalSeparator; + {$WARNINGS+} + for zG:=low(zG) to high(zG) do + _mZeit[zG]:=strtoint(erstesArgument(s,#9)); + for mG:=high(mG) downto low(mG) do + _mW[mG]:=strtofloat(erstesArgument(s,#9)); + while _mZeit[zgStunde]>=24 do begin + _mZeit[zgStunde]:=_mZeit[zgStunde]-24; + inc(_mZeit[zgTag]); + if _mZeit[zgTag]>30+byte(_mZeit[zgMonat] in [1,3,5,7,8,10,12])-(2-byte(_mZeit[zgJahr] mod 4 = 0))*byte(_mZeit[zgMonat]=2) then begin + _mZeit[zgTag]:=1; + inc(_mZeit[zgMonat]); + if _mZeit[zgMonat]>12 then begin + _mZeit[zgMonat]:=1; + inc(_mZeit[zgJahr]); + end; + end; + end; + setzeUZeit; + end + else begin // Format wie im Netz + + delete(s,1,pos('<BODY',uppercase(s))-1); + s:=copy(s,1,pos('</BODY>',uppercase(s))); + delete(s,1,pos('<CENTER>',uppercase(s))); + delete(s,1,pos('>',s)); + s:=trim(s); + t:=trim(leftStr(s,pos('<',s)-1)); + if not strZuMZeit(t,_mZeit) then + exit; + {$WARNINGS-} + if decimalSeparator<>'.' then + while pos('.',s)>0 do + s[pos('.',s)]:=decimalSeparator; + {$WARNINGS+} + for mG:=low(mG) to high(mG) do begin + delete(s,1,pos(uppercase(messNamen[mG]),uppercase(s))); + delete(s,1,pos('>',s)); + t:=trim(leftStr(s,pos('<',S)-1)); + istZahl:=t<>''; + for i:=1 to length(t) do + istZahl:=istZahl and (t[i] in ['0'..'9','.',',','-']); + if not istZahl then + exit; + _mW[mG]:=strtofloat(t); + end; + setzeUZeit; + end; + result:=true; +end; + +function tMessPunkt.schreibe: string; +var + zG: tZeitGroesze; + mG: tMessGroesze; +begin + result:=''; + for zG:=low(zG) to high(zG) do + result:=result+#9+inttostr(_mZeit[zG]); + for mG:=high(mG) downto low(mG) do + result:=result+#9+floattostr(mW[mG]); + result:=trim(result); +end; + +// tMessPunkteListe ************************************************************ + +constructor tMessPunkteListe.create; +begin + inherited create; + inhalt:=tFPList.create; +end; + +destructor tMessPunkteListe.destroy; +begin + inhalt.free; + inherited destroy; +end; + +function tMessPunkteListe.rItem(i: longint): tMessPunkt; +begin + result:=tMessPunkt(inhalt[i]); +end; + +function tMessPunkteListe.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; + +function tMessPunkteListe.add(s: string): boolean; +var + nm: tMessPunkt; + i: longint; +begin + result:=false; + nm:=tMessPunkt.create; + if not nm.lade(s) then begin + nm.free; + exit; + end; + i:=bisekt(nm.zeit); + result:=true; + if (i>=count) or (items[i].zeit<>nm.zeit) then + inhalt.Insert(i,nm) + else + nm.free; +end; + +function tMessPunkteListe.last: tMessPunkt; +begin + result:=items[count-1]; +end; + +function tMessPunkteListe.count: longint; +begin + result:=inhalt.count; +end; + +function tMessPunkteListe.minMaxY(startZeit,stopZeit: extended): tMessWerteExtPoints; +var + i: longint; + mG: tMessGroesze; +begin + i:=bisekt(startZeit); + for mG:=low(mG) to high(mG) do begin + result[mG,'x']:=items[i].mW[mG]; + result[mG,'y']:=result[mG,'x']; + end; + while (i<count) and (items[i].zeit<=stopZeit) do begin + for mG:=low(mG) to high(mG) do begin + result[mG,'x']:=min(result[mG,'x'],items[i].mW[mG]); + result[mG,'y']:=max(result[mG,'y'],items[i].mW[mG]); + end; + inc(i); + end; +end; + +// tMessPunkteUpdateThread ***************************************************** + +constructor tMessPunkteUpdateThread.create(besitzer: tMessPunkte; tNum,tAnz: longint); +begin + inherited create(true); + _besitzer:=besitzer; + fillchar(antwort,sizeof(antwort),#0); + setlength(antwort,0); + ladeProzess:=nil; + beendet:=false; + _tNum:=tNum; + _tAnz:=tAnz; + beenden:=false; + warGueltig:=false; + nZeitNullen; + suspended:=false; +end; + +destructor tMessPunkteUpdateThread.destroy; +begin + while not beendet do + sleep(100); + setlength(antwort,0); + inherited destroy; +end; + +procedure tMessPunkteUpdateThread.uebernehmen; +begin + if beenden then exit; + warGueltig:=_besitzer.einlesen(antwort); + setlength(antwort,0); + if (not warGueltig) or (20*random<1) then + form1.zeichnen; +end; + +procedure tMessPunkteUpdateThread.nZeitNullen; +var + lIch: longint; +begin + if beenden then exit; + lIch:=_besitzer.werte.count-1; + while round(_besitzer.werte[lIch].zeit*24*6) mod _tAnz <> _tNum do + dec(lIch); + nZeit:=_besitzer.werte[lIch].zeit + _tAnz*1/24/6; +end; + +procedure tMessPunkteUpdateThread.execute; +var + bytesToRead,bytesRead,cnt: longint; + mZeit: tZeit; +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('--data'); + uZeit2mZeit(nZeit,mZeit); + ladeProzess.parameters.add( + 'tag='+inttostr(mZeit[zgTag])+'&'+ + 'monat='+Monatsnamen[mZeit[zgMonat]]+'&'+ + 'jahr='+inttostr(mZeit[zgJahr])+'&'+ + 'stunde='+inttostr(mZeit[zgStunde])+'&'+ + 'minute='+inttostr(10*mZeit[zgMin10])+'&'+ + 'submit=Abfrage starten'); + ladeProzess.parameters.add('http://wetter.mb.fh-jena.de/station/datenbank/php_alt/abfrage1.php'); + 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(10); + end; + ladeProzess.closeOutput; + ladeProzess.free; + + if not beenden then begin + setlength(antwort,bytesRead); + + synchronize(@uebernehmen); + + if (nZeit<=now) or warGueltig then + nZeit:=nZeit + _tAnz*1/24/6 + else begin + synchronize(@nZeitNullen); + for cnt:=0 to 599 do begin + if beenden then + break; + sleep(100); + end; + end; + end; + end; + ladeProzess:=nil; + beendet:=true; +end; + +// tMessPunkte ***************************************************************** + +constructor tMessPunkte.create(zeichenFlaeche: tImage); +begin + inherited create; + bild:=zeichenFlaeche; + werte:=tMessPunkteListe.create; + fillchar(muts,sizeof(muts),#0); + setlength(muts,0); +end; + +destructor tMessPunkte.destroy; +var + i: longint; +begin + werte.free; + for i:=0 to length(muts)-1 do + muts[i].free; + setlength(muts,0); + inherited destroy; +end; + +function tMessPunkte.einlesen(was: string): boolean; +begin + result:=werte.add(was); +end; + +procedure tMessPunkte.laden(von: string); +var + f: textfile; + s: string; + i: longint; +begin + if not fileexists(von) then begin + writeln('Messwertedatei '''+von+''' existiert nicht!'); + raise exception.create('Messwertedatei '''+von+''' existiert nicht!'); + exit; + end; + assignfile(f,von); + reset(f); + while not eof(f) do begin + readln(f,s); + werte.add(s); + end; + closefile(f); + if length(muts)=0 then begin + setlength(muts,20); + for i:=0 to length(muts)-1 do + muts[i]:=tMessPunkteUpdateThread.create(self,i,length(muts)); + end; +end; + +procedure tMessPunkte.speichern(nach: string); +var + dateischonda: boolean; + f: textfile; + i: longint; +begin + dateischonda:=fileexists(nach); + if dateischonda then + assignfile(f,mkTemp(nach+'.XXXXXX')) + else + assignfile(f,nach); + rewrite(f); + for i:=0 to werte.count-1 do + writeln(f,werte[i].schreibe); + closefile(f); + if dateischonda then begin + deletefile(nach); + rename(f,nach); + end; +end; + +procedure tMessPunkte.achsenZeichnen(zuZeichnen: tMessGroeszenSet; startZeit,stopZeit: extended); +var + mG: tMessGroesze; + miMa: tMessWerteExtPoints; + dY,cY: extended; +begin + miMa:=werte.minMaxY(startZeit,stopZeit); + for mG:=high(mG) downto low(mG) do + if mG in zuZeichnen then begin + bild.canvas.pen.color:=farben[mG]; + dY:=power(10,ceil(ln(max(1e-9,miMa[mG,'y']-miMa[mG,'x']))/ln(10))); + repeat + if max(1e-9,miMa[mG,'y']-miMa[mG,'x'])/dY>=3 then continue; + dY:=dY/10*3; + if max(1e-9,miMa[mG,'y']-miMa[mG,'x'])/dY>=3 then continue; + dY:=dY/3; + until max(1e-9,miMa[mG,'y']-miMa[mG,'x'])/dY>=3; + cY:=ceil(miMa[mG,'x']/dY)*dY; + while cY<=miMa[mG,'y'] do begin + bild.canvas.moveTo(-10,wertZuY(cY,miMa[mG],bild.height)); + bild.canvas.lineTo(bild.width+10,wertZuY(cY,miMa[mG],bild.height)); + cY:=cY+dY; + end; + end; +end; + +procedure tMessPunkte.graphenZeichnen(zuZeichnen: tMessGroeszenSet; startZeit,stopZeit: extended); +var + mG: tMessGroesze; + miMa: tMessWerteExtPoints; + i: longint; +begin + miMa:=werte.minMaxY(startZeit,stopZeit); + for mG:=high(mG) downto low(mG) do + if mG in zuZeichnen then begin + bild.canvas.pen.color:=farben[mG]; + i:=werte.bisekt(startZeit); + bild.canvas.moveTo( + -10, + wertZuY(werte[i].mW[mG],miMa[mG],bild.height) + ); + while (i<werte.count) and (werte[i].zeit<=stopZeit) do begin + bild.canvas.lineTo( + wertZuX(werte[i].zeit,startZeit,stopZeit,bild.width), + wertZuY(werte[i].mW[mG],miMa[mG],bild.height) + ); + inc(i); + end; + end; +end; + +procedure tMessPunkte.mutBeenden; +var + i: longint; +begin + for i:=0 to length(muts)-1 do + muts[i].beenden:=true; +end; + +// allgemeine Funktionen ******************************************************* + +procedure uZeit2mZeit(uZ: extended; out mZ: tZeit); inline; +var + mi,se,hu: word; +begin + decodeDate(uZ,mZ[zgJahr],mZ[zgMonat],mZ[zgTag]); + decodeTime(uZ,mZ[zgStunde],mi,se,hu); + mZ[zgMin10]:=round(mi/10); +end; + +function strZuMZeit(s: string; out mZ: tZeit): boolean; +var + t: string; + i: longint; +begin + result:=false; + s:=trim(s); + if pos('.',s)=0 then exit; + t:=erstesArgument(s,'.'); + if t='' then exit; + for i:=1 to length(t) do + if not (t[i] in ['0'..'9']) then exit; + mZ[zgTag]:=strtoint(t); + t:=erstesArgument(s); + mZ[zgMonat]:=1; + while (mZ[zgMonat]<=12) and (monatsNamen[mZ[zgMonat]]<>t) do + inc(mZ[zgMonat]); + if mZ[zgMonat]>12 then + exit; + t:=erstesArgument(s); + if t='' then exit; + for i:=1 to length(t) do + if not (t[i] in ['0'..'9']) then exit; + mZ[zgJahr]:=strtoint(t); + t:=erstesArgument(s,':'); + if t='' then exit; + for i:=1 to length(t) do + if not (t[i] in ['0'..'9']) then exit; + mZ[zgStunde]:=strtoint(t); + t:=erstesArgument(s); + if t='' then exit; + for i:=1 to length(t) do + if not (t[i] in ['0'..'9']) then exit; + mZ[zgMin10]:=strtoint(t) div 10; + result:=(strtoint(t) mod 10) = 0; +end; + end. diff --git a/pegelunit.pas b/pegelunit.pas index 3fe1529..033ea3d 100644 --- a/pegelunit.pas +++ b/pegelunit.pas @@ -106,7 +106,6 @@ const (130,170,210,230),(200,230,260,290),(130,150,170,190),(0,0,0,0)); pegelFarben: array[tPegelstation] of tColor = ($000000,$000000,$000000,$FF0000,$7F0000,$000000,$000000,$000000,$000000,$000000,$000000,$000000); - bufLengMin = 1024*1024; // tPegelStand ***************************************************************** @@ -362,6 +361,76 @@ begin inherited destroy; 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; + procedure tPegelStaende.laden(von: string); var f: textfile; @@ -426,7 +495,7 @@ begin for ps:=low(tPegelStation) to high(tPegelStation) do begin writeln(f,'Station: '+Pegelstationsnamen[ps,0]); for i:=0 to werte[ps].Count-1 do - writeln(f,tPegelStand(werte[ps][i]).schreibe); + writeln(f,werte[ps][i].schreibe); end; closefile(f); if dateischonda then begin @@ -474,76 +543,6 @@ begin 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; - procedure tPegelStaende.putBeenden; begin put.beenden:=true; @@ -3,6 +3,7 @@ object Form1: TForm1 Height = 204 Top = 256 Width = 713 + BorderStyle = bsNone Caption = 'Form1' ClientHeight = 204 ClientWidth = 713 @@ -3,7 +3,8 @@ unit Unit1; interface uses - Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, pegelUnit; + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, + pegelUnit, fhUnit, lowLevelUnit; type @@ -17,9 +18,10 @@ type procedure FormDestroy(Sender: TObject); private { private declarations } - datenZeitRaum: extended; - pegel: tPegelStaende; - pegelDatei: string; + datenZeitRaum: extended; + pegel: tPegelStaende; + wetter: tMessPunkte; + pegelDatei,wetterDatei: string; public { public declarations } procedure zeichnen; @@ -31,10 +33,7 @@ var fehler: boolean; const - - DateiName = 'letztes_Wetter.txt'; - PegelDateiName = 'letzte_Pegel.txt'; - anzDaten = 7*24*6*4; + bufLengMin = 1024*1024; (* @@ -49,14 +48,16 @@ function letzterMonat(t: TDateTime): TPoint; // x=Monat, y=Jahr function MyIntToStr(I,Ziff: longint): string; *) -function wertZuX(w: extended; startZeit,stopZeit: extended; breite: longint): longint; -function wertZuY(w: extended; miMa: tPoint; hoehe: longint): longint; +function wertZuX(w: extended; startZeit,stopZeit: extended; breite: longint): longint; inline; +function wertZuY(w: extended; miMa: tPoint; hoehe: longint): longint; inline; overload; +function wertZuY(w: extended; miMa: tExtPoint; hoehe: longint): longint; inline; overload; +function wertZuY(w: extended; mi,ma: extended; hoehe: longint): longint; inline; overload; implementation {$R *.lfm} -uses process, myStringListUnit, lowLevelUnit, systemUnit, matheunit, math; +uses process, myStringListUnit, systemUnit, matheunit, math; { TForm1 } @@ -67,17 +68,18 @@ var fi: textfile; args: array of string; begin + fehler:=true; __ausgabenMaske:=1; pidDatei:=''; pegelDatei:=''; datenZeitRaum:=1; - fehler:=true; s:=extractfilepath(application.exename)+'wetter.konf'; t:=''; if not fileexists(s) then raise exception.create('Kann Konfigurationsdatei '''+s+''' nicht finden!'); pegel:=tPegelStaende.create(image1); + wetter:=tMessPunkte.create(image1); f:=tMyStringList.create; f.loadFromFile(s); f.unfoldMacros; @@ -118,6 +120,13 @@ begin pegel.laden(pegelDatei); continue; end; + if startetMit('wetterDatei:',s) then begin + wetterDatei:=s; + if pos('/',wetterDatei)=0 then + wetterDatei:=extractFilePath(application.exename)+wetterDatei; + wetter.laden(wetterDatei); + continue; + end; if startetMit('datenZeitRaum:',s) then begin datenZeitRaum:=exprtofloat(false,s,nil,nil); continue; @@ -136,6 +145,7 @@ end; procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction); begin pegel.putBeenden; + wetter.mutBeenden; end; procedure TForm1.FormDestroy(Sender: TObject); @@ -145,8 +155,11 @@ begin if not fehler then begin if pegelDatei<>'' then pegel.speichern(pegelDatei); + if wetterDatei<>'' then + wetter.speichern(wetterDatei); end; pegel.free; + wetter.free; end; procedure TForm1.zeichnen; @@ -160,6 +173,7 @@ begin startZeit:=stopZeit-datenZeitRaum; pegel.achsenZeichnen([psRudolstadt,psRothenstein],startZeit,stopZeit); + wetter.achsenZeichnen([mgTemperatur],startZeit,stopZeit); image1.canvas.pen.color:=$000000; tmp:=floor(startZeit); @@ -170,6 +184,7 @@ begin end; pegel.graphenZeichnen([psRudolstadt,psRothenstein],now-datenZeitRaum,now); + wetter.graphenZeichnen([mgTemperatur,mgLuftfeuchte,mgNiederschlag,mgGlobalstrahlung,mgLuftdruck],now-datenZeitRaum,now); fehler:=false; end; @@ -182,12 +197,22 @@ var tmp: extended; begin tmp:=(w-startZeit)/(stopZeit-startZeit); - result:=round(-breite*ln(1+tmp*(exp(-xScale)-1))/xScale); + result:=1+round(-(breite-2)*ln(1+tmp*(exp(-xScale)-1))/xScale); end; function wertZuY(w: extended; miMa: tPoint; hoehe: longint): longint; begin - result:=round((w-miMa.x)/(miMa.y-miMa.x)*hoehe); + result:=wertZuY(w,miMa.x,miMa.y,hoehe); +end; + +function wertZuY(w: extended; miMa: tExtPoint; hoehe: longint): longint; +begin + result:=wertZuY(w,miMa['x'],miMa['y'],hoehe); +end; + +function wertZuY(w: extended; mi,ma: extended; hoehe: longint): longint; +begin + result:=hoehe-1-round((w-mi)/(ma-mi)*(hoehe-2)); end; end. diff --git a/wetter.konf b/wetter.konf index 2f3e5cb..264a14e 100644 --- a/wetter.konf +++ b/wetter.konf @@ -1,4 +1,4 @@ pidDatei: /tmp/wetter.pid -#wetterDatei: letztes_Wetter.txt +wetterDatei: letztes_Wetter.txt pegelDatei: letzte_Pegel.txt datenZeitRaum: 7*4 @@ -9,7 +9,7 @@ <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> <CursorPos X="12" Y="6"/> - <UsageCount Value="33"/> + <UsageCount Value="42"/> </Unit0> <Unit1> <Filename Value="unit1.pas"/> @@ -18,9 +18,10 @@ <HasResources Value="True"/> <ResourceBaseClass Value="Form"/> <UnitName Value="Unit1"/> - <TopLine Value="135"/> - <CursorPos X="20" Y="138"/> - <UsageCount Value="33"/> + <IsVisibleTab Value="True"/> + <TopLine Value="179"/> + <CursorPos X="49" Y="215"/> + <UsageCount Value="42"/> <Loaded Value="True"/> <LoadedDesigner Value="True"/> </Unit1> @@ -28,31 +29,29 @@ <Filename Value="original/pegelunit.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> - <UsageCount Value="33"/> + <UsageCount Value="42"/> </Unit2> <Unit3> <Filename Value="fhunit.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="2"/> - <CursorPos X="28" Y="30"/> - <UsageCount Value="33"/> + <UsageCount Value="42"/> <Loaded Value="True"/> </Unit3> <Unit4> <Filename Value="original/Unit1.pas"/> <EditorIndex Value="4"/> - <TopLine Value="209"/> - <CursorPos X="53" Y="108"/> - <UsageCount Value="17"/> + <TopLine Value="665"/> + <CursorPos X="120" Y="465"/> + <UsageCount Value="21"/> <Loaded Value="True"/> </Unit4> <Unit5> <Filename Value="pegelunit.pas"/> - <IsVisibleTab Value="True"/> <EditorIndex Value="3"/> - <TopLine Value="289"/> - <CursorPos X="56" Y="296"/> - <UsageCount Value="17"/> + <TopLine Value="393"/> + <CursorPos Y="432"/> + <UsageCount Value="21"/> <Loaded Value="True"/> </Unit5> <Unit6> @@ -60,13 +59,13 @@ <EditorIndex Value="-1"/> <TopLine Value="116"/> <CursorPos Y="159"/> - <UsageCount Value="9"/> + <UsageCount Value="8"/> </Unit6> <Unit7> <Filename Value="wetter.konf"/> <EditorIndex Value="1"/> - <CursorPos X="18" Y="4"/> - <UsageCount Value="17"/> + <CursorPos X="13" Y="2"/> + <UsageCount Value="21"/> <Loaded Value="True"/> <DefaultSyntaxHighlighter Value="None"/> </Unit7> @@ -75,7 +74,7 @@ <EditorIndex Value="-1"/> <TopLine Value="157"/> <CursorPos X="73" Y="178"/> - <UsageCount Value="9"/> + <UsageCount Value="8"/> </Unit8> <Unit9> <Filename Value="/usr/lib/lazarus/components/lazutils/lazutf8.pas"/> @@ -83,150 +82,147 @@ <EditorIndex Value="-1"/> <TopLine Value="150"/> <CursorPos X="3" Y="171"/> - <UsageCount Value="9"/> + <UsageCount Value="8"/> </Unit9> <Unit10> <Filename Value="../units/mystringlistunit.pas"/> <EditorIndex Value="-1"/> <CursorPos X="47" Y="8"/> - <UsageCount Value="9"/> + <UsageCount Value="8"/> </Unit10> <Unit11> <Filename Value="../units/lowlevelunit.pas"/> <EditorIndex Value="-1"/> <TopLine Value="697"/> <CursorPos X="43" Y="843"/> - <UsageCount Value="10"/> + <UsageCount Value="9"/> </Unit11> <Unit12> <Filename Value="letzte_Pegel.txt"/> <EditorIndex Value="-1"/> <TopLine Value="949303"/> <CursorPos X="17" Y="949336"/> - <UsageCount Value="9"/> + <UsageCount Value="8"/> <DefaultSyntaxHighlighter Value="None"/> </Unit12> </Units> - <JumpHistory Count="30" HistoryIndex="29"> + <JumpHistory Count="29" HistoryIndex="28"> <Position1> - <Filename Value="pegelunit.pas"/> - <Caret Line="54" Column="18" TopLine="43"/> + <Filename Value="fhunit.pas"/> + <Caret Line="184" Column="37" TopLine="164"/> </Position1> <Position2> - <Filename Value="pegelunit.pas"/> - <Caret Line="255" Column="31" TopLine="241"/> + <Filename Value="fhunit.pas"/> + <Caret Line="185" Column="19" TopLine="179"/> </Position2> <Position3> - <Filename Value="pegelunit.pas"/> - <Caret Line="286" Column="17" TopLine="255"/> + <Filename Value="fhunit.pas"/> + <Caret Line="534" Column="36" TopLine="532"/> </Position3> <Position4> - <Filename Value="pegelunit.pas"/> - <Caret Line="283" Column="23" TopLine="265"/> + <Filename Value="fhunit.pas"/> + <Caret Line="89" Column="36" TopLine="78"/> </Position4> <Position5> - <Filename Value="pegelunit.pas"/> - <Caret Line="106" Column="26" TopLine="78"/> + <Filename Value="fhunit.pas"/> + <Caret Line="481" Column="49" TopLine="433"/> </Position5> <Position6> - <Filename Value="original/Unit1.pas"/> - <Caret Line="1069" Column="76" TopLine="1043"/> + <Filename Value="fhunit.pas"/> + <Caret Line="76" Column="20" TopLine="62"/> </Position6> <Position7> - <Filename Value="original/Unit1.pas"/> + <Filename Value="fhunit.pas"/> + <Caret Line="424" Column="21" TopLine="393"/> </Position7> <Position8> - <Filename Value="pegelunit.pas"/> - <Caret Line="288" Column="60" TopLine="264"/> + <Filename Value="fhunit.pas"/> + <Caret Line="437" Column="14" TopLine="430"/> </Position8> <Position9> - <Filename Value="pegelunit.pas"/> - <Caret Line="291" Column="78" TopLine="264"/> + <Filename Value="fhunit.pas"/> + <Caret Line="454" Column="67" TopLine="435"/> </Position9> <Position10> - <Filename Value="pegelunit.pas"/> - <Caret Line="281" Column="14" TopLine="275"/> + <Filename Value="fhunit.pas"/> + <Caret Line="68" Column="45" TopLine="41"/> </Position10> <Position11> - <Filename Value="pegelunit.pas"/> - <Caret Line="300" Column="39" TopLine="79"/> + <Filename Value="fhunit.pas"/> + <Caret Line="64" Column="27" TopLine="45"/> </Position11> <Position12> - <Filename Value="pegelunit.pas"/> - <Caret Line="310" Column="30" TopLine="281"/> + <Filename Value="fhunit.pas"/> + <Caret Line="325" Column="14" TopLine="314"/> </Position12> <Position13> - <Filename Value="pegelunit.pas"/> - <Caret Line="298" Column="44" TopLine="281"/> + <Filename Value="fhunit.pas"/> + <Caret Line="352" Column="47" TopLine="339"/> </Position13> <Position14> - <Filename Value="unit1.pas"/> - <Caret Line="3" Column="4"/> + <Filename Value="fhunit.pas"/> + <Caret Line="355" Column="31" TopLine="332"/> </Position14> <Position15> - <Filename Value="pegelunit.pas"/> - <Caret Line="391" Column="36" TopLine="357"/> + <Filename Value="fhunit.pas"/> + <Caret Line="537" Column="30" TopLine="512"/> </Position15> <Position16> - <Filename Value="pegelunit.pas"/> - <Caret Line="501" Column="3" TopLine="475"/> + <Filename Value="fhunit.pas"/> + <Caret Line="219" Column="56" TopLine="190"/> </Position16> <Position17> - <Filename Value="pegelunit.pas"/> - <Caret Line="499" Column="22" TopLine="476"/> + <Filename Value="fhunit.pas"/> + <Caret Line="165" TopLine="130"/> </Position17> <Position18> - <Filename Value="pegelunit.pas"/> - <Caret Line="224" Column="56" TopLine="196"/> + <Filename Value="fhunit.pas"/> + <Caret Line="88" Column="83" TopLine="73"/> </Position18> <Position19> - <Filename Value="pegelunit.pas"/> - <Caret Line="166" Column="22" TopLine="146"/> + <Filename Value="fhunit.pas"/> + <Caret Line="524" Column="49" TopLine="504"/> </Position19> <Position20> - <Filename Value="pegelunit.pas"/> - <Caret Line="482" Column="20" TopLine="449"/> + <Filename Value="fhunit.pas"/> + <Caret Line="97" TopLine="78"/> </Position20> <Position21> - <Filename Value="pegelunit.pas"/> - <Caret Line="8" Column="59"/> + <Filename Value="fhunit.pas"/> + <Caret Line="160" TopLine="159"/> </Position21> <Position22> - <Filename Value="pegelunit.pas"/> - <Caret Line="305" Column="45" TopLine="290"/> + <Filename Value="fhunit.pas"/> + <Caret Line="165" Column="19" TopLine="153"/> </Position22> <Position23> - <Filename Value="pegelunit.pas"/> - <Caret Line="271" TopLine="255"/> + <Filename Value="fhunit.pas"/> + <Caret Line="12" Column="63"/> </Position23> <Position24> - <Filename Value="pegelunit.pas"/> - <Caret Line="358" Column="44" TopLine="295"/> + <Filename Value="fhunit.pas"/> + <Caret Line="165" TopLine="146"/> </Position24> <Position25> - <Filename Value="pegelunit.pas"/> - <Caret Line="81" TopLine="55"/> + <Filename Value="fhunit.pas"/> + <Caret Line="542" Column="24" TopLine="516"/> </Position25> <Position26> - <Filename Value="pegelunit.pas"/> - <Caret Line="550" Column="3" TopLine="514"/> + <Filename Value="fhunit.pas"/> + <Caret Line="16" Column="57"/> </Position26> <Position27> - <Filename Value="pegelunit.pas"/> - <Caret Line="80" Column="18" TopLine="60"/> + <Filename Value="fhunit.pas"/> + <Caret Line="107" Column="29" TopLine="81"/> </Position27> <Position28> - <Filename Value="pegelunit.pas"/> - <Caret Line="550" Column="6" TopLine="514"/> + <Filename Value="fhunit.pas"/> + <Caret Line="8" Column="73"/> </Position28> <Position29> - <Filename Value="unit1.pas"/> - <Caret Line="150" TopLine="122"/> + <Filename Value="fhunit.pas"/> + <Caret Line="535" TopLine="525"/> </Position29> - <Position30> - <Filename Value="original/Unit1.pas"/> - <Caret Line="374" Column="49" TopLine="368"/> - </Position30> </JumpHistory> </ProjectSession> </CONFIG> |