diff --git a/entries/rlawson/src/parser.pas b/entries/rlawson/src/parser.pas
index 87b6250..c1d3e97 100644
--- a/entries/rlawson/src/parser.pas
+++ b/entries/rlawson/src/parser.pas
@@ -5,7 +5,7 @@
interface
uses
- Classes, SysUtils, bufstream, Contnrs, Math;
+ Classes, SysUtils, bufstream, Contnrs, Math, util;
procedure ReadMeasurements(inputFile: string);
@@ -44,12 +44,12 @@ procedure ProcessMeasurements(var buffer: array of char; bufferLength: integer;
begin
while idx < (bufferLength - 1) do
begin
- // read the city until separator
- //city := '';
+ // read the city by looking for semicolon
+ city := '';
cityStart := idx;
while buffer[idx] <> REC_SEP do Inc(idx);
SetString(city, @buffer[cityStart], (idx - cityStart));
- // increment through temp reading and calculate integer temp (*100)
+ // parse the temp reading
Inc(idx); // move pointer past the ;
currentTempSign := 1;
// check for negative sign, if so flag the multiplier and then move past neg sign
@@ -59,20 +59,16 @@ procedure ProcessMeasurements(var buffer: array of char; bufferLength: integer;
Inc(idx);
end;
// look ahead - is decimal point 2 spaces away then we have two digits
+ temp := 0;
if buffer[idx + 2] = DECIMAL_POINT then
begin
- temp := currentTempSign * (100 * byte(buffer[idx]) + 10 *
- byte(buffer[idx + 1]) + byte(buffer[idx + 2]) - 5328);
- // move past digits and CRLF and position pointer to first character of next record
- idx := idx + 6;
- end
- else
- begin
- temp := currentTempSign * (10 * byte(buffer[idx + 1]) +
- byte(buffer[idx + 2]) - 528);
- // move past digits and CRLF and position pointer to first character of next record
- idx := idx + 5;
+ temp := 100 * (byte(buffer[idx]) - ANSI_ZERO);
+ Inc(idx);
end;
+ temp := temp + 10 * (byte(buffer[idx]) - ANSI_ZERO);
+ idx := idx + 2;
+ temp := currentTempSign * (temp + (byte(buffer[idx]) - ANSI_ZERO));
+ idx := idx + 3;
reading := results.Find(city);
if reading = nil then
begin
@@ -94,51 +90,6 @@ procedure ProcessMeasurements(var buffer: array of char; bufferLength: integer;
end;
end;
-function PascalRound(x: double): double;
-var
- t: double;
-begin
- //round towards positive infinity
- t := Trunc(x);
- if (x < 0.0) and (t - x = 0.5) then
- begin
- // Do nothing
- end
- else if Abs(x - t) >= 0.5 then
- begin
- t := t + Math.Sign(x);
- end;
-
- if t = 0.0 then
- Result := 0.0
- else
- Result := t;
-end;
-
-
-function RoundEx(x: double): double;
-begin
- Result := PascalRound(x * 10.0) / 10.0;
-end;
-
-function Compare(AList: TStringList; AIndex1, AIndex2: integer): integer;
-var
- Pos1, Pos2: integer;
- Str1, Str2: string;
-begin
- Result := 0;
- Str1 := AList.Strings[AIndex1];
- Str2 := AList.Strings[AIndex2];
- Pos1 := Pos('=', Str1);
- Pos2 := Pos('=', Str2);
- if (Pos1 > 0) and (Pos2 > 0) then
- begin
- Str1 := Copy(Str1, 1, Pos1 - 1);
- Str2 := Copy(Str2, 1, Pos2 - 1);
- Result := CompareStr(Str1, Str2);
- end;
-end;
-
procedure DumpMeasurements(results: TFPHashList);
var
i: integer;
@@ -160,11 +111,6 @@ procedure DumpMeasurements(results: TFPHashList);
mean := RoundEx(reading^.total / reading^.numReadings / 10);
readingStr := reading^.city + '=' + FormatFloat('0.0', min) +
'/' + FormatFloat('0.0', mean) + '/' + FormatFloat('0.0', max);
- {$IFDEF DEBUG}
- readingStr := reading^.city + '=' + FormatFloat('0.0', min) +
- '/' + FormatFloat('0.0', mean) + '/' + FormatFloat('0.0', max) +
- '/' + IntToStr(reading^.total) + '/' + IntToStr(reading^.numReadings);
- {$ENDIF}
weatherStationList.Add(readingStr);
Dispose(reading);
end;
@@ -183,29 +129,6 @@ procedure DumpMeasurements(results: TFPHashList);
WriteLn('}');
end;
-
-procedure DumpExceptionCallStack(E: Exception);
-var
- I: integer;
- Frames: PPointer;
- Report: string;
-begin
- Report := 'Program exception! ' + LineEnding + 'Stacktrace:' +
- LineEnding + LineEnding;
- if E <> nil then
- begin
- Report := Report + 'Exception class: ' + E.ClassName + LineEnding +
- 'Message: ' + E.Message + LineEnding;
- end;
- Report := Report + BackTraceStrFunc(ExceptAddr);
- Frames := ExceptFrames;
- for I := 0 to ExceptFrameCount - 1 do
- Report := Report + LineEnding + BackTraceStrFunc(Frames[I]);
- WriteLn(Report);
- Halt; // End of program execution
-end;
-
-
procedure ReadMeasurements(inputFile: string);
var
totalBytesRead, BytesRead: int64;
@@ -213,10 +136,7 @@ procedure ReadMeasurements(inputFile: string);
FileStream: TFileStream;
fileSize: int64;
ReadBufferStream: TReadBufStream;
- starttime: uint64;
- elapsedTimeSec, MBRead: double;
results: TFPHashList;
- currentChar: char;
idx: integer;
startOfNextRecord: string;
startOfNextRecordLength: integer;
@@ -228,50 +148,29 @@ procedure ReadMeasurements(inputFile: string);
ReadBufferStream := TReadBufStream.Create(FileStream);
fileSize := FileStream.size;
totalBytesRead := 0;
- starttime := GetTickCount64;
results := TFPHashList.Create;
startOfNextRecord := '';
while totalBytesRead <= fileSize do
// While the amount of data read is less than or equal to the size of the stream do
begin
startOfNextRecordLength := Length(startOfNextRecord);
- //WriteLn('startOfNextRecordLength: ', startOfNextRecordLength);
// if we have leftover from previous read then prepend it to this buffer
if startOfNextRecordLength > 0 then
Move(PChar(startOfNextRecord)^, Buffer[0], startOfNextRecordLength);
BytesRead := ReadBufferStream.Read(Buffer[startOfNextRecordLength], READ_SIZE);
- //WriteLn('Bytes read: ', BytesRead);
if BytesRead < 1 then break;
// now look in buffer backwards until we find the first LF
bufferLength := startOfNextRecordLength + BytesRead;
idx := bufferLength - 1;
- currentChar := buffer[idx];
- while (currentChar <> LF) do
- begin
- Dec(idx);
- currentChar := buffer[idx];
- end;
+ while (buffer[idx] <> LF) do Dec(idx);
ProcessMeasurements(Buffer, idx + 1, results);
startOfNextRecord := '';
startOfNextRecordLength := bufferLength - idx - 1;
- //WriteLn('startOfNextRecordLength: ', startOfNextRecordLength);
if startOfNextRecordLength > 0 then
SetString(startOfNextRecord, @buffer[idx + 1], startOfNextRecordLength);
Inc(totalBytesRead, BytesRead);
end;
DumpMeasurements(results);
- elapsedTimeSec := (GetTickCount64() - starttime) / 1000;
- MBRead := (totalBytesRead / (1024 * 1024));
- {$IFDEF DEBUG}
- WriteLn(inputFile);
- WriteLn('Buffer size: ', SizeOf(Buffer));
- WriteLn('Read size: ', READ_SIZE);
- WriteLn('File size: ', FileStream.Size);
- WriteLn('Total Bytes Read: ', totalBytesRead);
- WriteLn(Format('%f MB read', [MBRead]));
- WriteLn(Format('%f secs', [elapsedTimeSec]));
- WriteLn(Format('%f MB/s processed', [MBRead / elapsedTimeSec]));
- {$ENDIF}
ReadBufferStream.Free;
FileStream.Free;
results.Free;
diff --git a/entries/rlawson/src/util.pas b/entries/rlawson/src/util.pas
new file mode 100644
index 0000000..2537419
--- /dev/null
+++ b/entries/rlawson/src/util.pas
@@ -0,0 +1,82 @@
+unit util;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, Math;
+
+procedure DumpExceptionCallStack(E: Exception);
+function RoundEx(x: double): double;
+function Compare(AList: TStringList; AIndex1, AIndex2: integer): integer;
+
+implementation
+
+procedure DumpExceptionCallStack(E: Exception);
+var
+ I: integer;
+ Frames: PPointer;
+ Report: string;
+begin
+ Report := 'Program exception! ' + LineEnding + 'Stacktrace:' +
+ LineEnding + LineEnding;
+ if E <> nil then
+ begin
+ Report := Report + 'Exception class: ' + E.ClassName + LineEnding +
+ 'Message: ' + E.Message + LineEnding;
+ end;
+ Report := Report + BackTraceStrFunc(ExceptAddr);
+ Frames := ExceptFrames;
+ for I := 0 to ExceptFrameCount - 1 do
+ Report := Report + LineEnding + BackTraceStrFunc(Frames[I]);
+ WriteLn(Report);
+ Halt; // End of program execution
+end;
+
+function PascalRound(x: double): double;
+var
+ t: double;
+begin
+ //round towards positive infinity
+ t := Trunc(x);
+ if (x < 0.0) and (t - x = 0.5) then
+ begin
+ // Do nothing
+ end
+ else if Abs(x - t) >= 0.5 then
+ begin
+ t := t + Math.Sign(x);
+ end;
+
+ if t = 0.0 then
+ Result := 0.0
+ else
+ Result := t;
+end;
+
+
+function RoundEx(x: double): double;
+begin
+ Result := PascalRound(x * 10.0) / 10.0;
+end;
+
+function Compare(AList: TStringList; AIndex1, AIndex2: integer): integer;
+var
+ Pos1, Pos2: integer;
+ Str1, Str2: string;
+begin
+ Result := 0;
+ Str1 := AList.Strings[AIndex1];
+ Str2 := AList.Strings[AIndex2];
+ Pos1 := Pos('=', Str1);
+ Pos2 := Pos('=', Str2);
+ if (Pos1 > 0) and (Pos2 > 0) then
+ begin
+ Str1 := Copy(Str1, 1, Pos1 - 1);
+ Str2 := Copy(Str2, 1, Pos2 - 1);
+ Result := CompareStr(Str1, Str2);
+ end;
+end;
+
+end.
diff --git a/entries/rlawson/src/weather.lpi b/entries/rlawson/src/weather.lpi
index 5e316f3..1d6b891 100644
--- a/entries/rlawson/src/weather.lpi
+++ b/entries/rlawson/src/weather.lpi
@@ -83,7 +83,7 @@
-
+
@@ -92,6 +92,10 @@
+
+
+
+
diff --git a/entries/rlawson/src/weather.lpr b/entries/rlawson/src/weather.lpr
index e47ca4d..1e897af 100644
--- a/entries/rlawson/src/weather.lpr
+++ b/entries/rlawson/src/weather.lpr
@@ -4,11 +4,12 @@
uses
{$IFDEF UNIX}
- cthreads,
+ cmem, cthreads,
{$ENDIF}
Classes,
SysUtils,
- CustApp, parser;
+ CustApp,
+ parser;
type